Completed
Push — master ( 196a0a...af77e8 )
by Zack
11:10 queued 04:43
created

GravityView_frontend::getPostId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 15 and the first side effect is on line 1677.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * GravityView Frontend functions
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
15
class GravityView_frontend {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
16
17
	/**
18
	 * Regex strings that are used to determine whether the current request is a GravityView search or not.
19
	 * @see GravityView_frontend::is_searching()
20
	 * @since 1.7.4.1
21
	 * @var array
22
	 */
23
	private static $search_parameters = array( 'gv_search', 'gv_start', 'gv_end', 'gv_id', 'gv_by', 'filter_*' );
24
25
	/**
26
	 * Is the currently viewed post a `gravityview` post type?
27
	 * @var boolean
28
	 */
29
	var $is_gravityview_post_type = false;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $is_gravityview_post_type.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
30
31
	/**
32
	 * Does the current post have a `[gravityview]` shortcode?
33
	 * @var boolean
34
	 */
35
	var $post_has_shortcode = false;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $post_has_shortcode.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
36
37
	/**
38
	 * The Post ID of the currently viewed post. Not necessarily GV
39
	 * @var int
40
	 */
41
	var $post_id = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $post_id.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
42
43
	/**
44
	 * Are we currently viewing a single entry?
45
	 * If so, the int value of the entry ID. Otherwise, false.
46
	 * @var int|boolean
47
	 */
48
	var $single_entry = false;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $single_entry.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
49
50
	/**
51
	 * If we are viewing a single entry, the entry data
52
	 * @var array|false
53
	 */
54
	var $entry = false;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $entry.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
55
56
	/**
57
	 * When displaying the single entry we should always know to which View it belongs (the context is everything!)
58
	 * @var null
59
	 */
60
	var $context_view_id = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $context_view_id.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
61
62
	/**
63
	 * The View is showing search results
64
	 * @since 1.5.4
65
	 * @var boolean
66
	 */
67
	var $is_search = false;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $is_search.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
68
69
	/**
70
	 * The view data parsed from the $post
71
	 *
72
	 * @see  GravityView_View_Data::__construct()
73
	 * @var GravityView_View_Data
74
	 */
75
	var $gv_output_data = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $gv_output_data.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
76
77
	/**
78
	 * @var GravityView_frontend
79
	 */
80
	static $instance;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $instance.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
81
82
	/**
83
	 * Class constructor, enforce Singleton pattern
84
	 */
85
	private function __construct() {}
86
87 2
	private function initialize() {
88 2
		add_action( 'wp', array( $this, 'parse_content'), 11 );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
89 2
		add_filter( 'parse_query', array( $this, 'parse_query_fix_frontpage' ), 10 );
90 2
		add_action( 'template_redirect', array( $this, 'set_entry_data'), 1 );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
91
92
		// Enqueue scripts and styles after GravityView_Template::register_styles()
93 2
		add_action( 'wp_enqueue_scripts', array( $this, 'add_scripts_and_styles' ), 20 );
94
95
		// Enqueue and print styles in the footer. Added 1 priorty so stuff gets printed at 10 priority.
96 2
		add_action( 'wp_print_footer_scripts', array( $this, 'add_scripts_and_styles' ), 1 );
97
98 2
		add_filter( 'the_title', array( $this, 'single_entry_title' ), 1, 2 );
99 2
		add_filter( 'the_content', array( $this, 'insert_view_in_content' ) );
100 2
		add_filter( 'comments_open', array( $this, 'comments_open' ), 10, 2 );
101
102 2
		add_action( 'gravityview_after', array( $this, 'context_not_configured_warning' ) );
103 2
	}
104
105
	/**
106
	 * Get the one true instantiated self
107
	 * @return GravityView_frontend
108
	 */
109 2
	public static function getInstance() {
0 ignored issues
show
Coding Style introduced by
The function name getInstance is in camel caps, but expected get_instance instead as per the coding standard.
Loading history...
110
111 2
		if ( empty( self::$instance ) ) {
112 2
			self::$instance = new self;
113 2
			self::$instance->initialize();
114
		}
115
116 2
		return self::$instance;
117
	}
118
119
	/**
120
	 * @return GravityView_View_Data
121
	 */
122
	public function getGvOutputData() {
0 ignored issues
show
Coding Style introduced by
The function name getGvOutputData is in camel caps, but expected get_gv_output_data instead as per the coding standard.
Loading history...
123
		return $this->gv_output_data;
124
	}
125
126
	/**
127
	 * @param GravityView_View_Data $gv_output_data
128
	 */
129
	public function setGvOutputData( $gv_output_data ) {
0 ignored issues
show
Coding Style introduced by
The function name setGvOutputData is in camel caps, but expected set_gv_output_data instead as per the coding standard.
Loading history...
130
		$this->gv_output_data = $gv_output_data;
131
	}
132
133
	/**
134
	 * @return boolean
135
	 */
136
	public function isSearch() {
0 ignored issues
show
Coding Style introduced by
The function name isSearch is in camel caps, but expected is_search instead as per the coding standard.
Loading history...
137
		return $this->is_search;
138
	}
139
140
	/**
141
	 * @param boolean $is_search
142
	 */
143
	public function setIsSearch( $is_search ) {
0 ignored issues
show
Coding Style introduced by
The function name setIsSearch is in camel caps, but expected set_is_search instead as per the coding standard.
Loading history...
144
		$this->is_search = $is_search;
145
	}
146
147
	/**
148
	 * @return bool|int
149
	 */
150 1
	public function getSingleEntry() {
0 ignored issues
show
Coding Style introduced by
The function name getSingleEntry is in camel caps, but expected get_single_entry instead as per the coding standard.
Loading history...
151 1
		return $this->single_entry;
152
	}
153
154
	/**
155
	 * Sets the single entry ID and also the entry
156
	 * @param bool|int|string $single_entry
157
	 */
158
	public function setSingleEntry( $single_entry ) {
0 ignored issues
show
Coding Style introduced by
The function name setSingleEntry is in camel caps, but expected set_single_entry instead as per the coding standard.
Loading history...
159
160
		$this->single_entry = $single_entry;
161
162
	}
163
164
	/**
165
	 * @return array
166
	 */
167
	public function getEntry() {
0 ignored issues
show
Coding Style introduced by
The function name getEntry is in camel caps, but expected get_entry instead as per the coding standard.
Loading history...
168
		return $this->entry;
169
	}
170
171
	/**
172
	 * Set the current entry
173
	 * @param array|int $entry Entry array or entry slug or ID
174
	 */
175
	public function setEntry( $entry ) {
0 ignored issues
show
Coding Style introduced by
The function name setEntry is in camel caps, but expected set_entry instead as per the coding standard.
Loading history...
176
177
		if ( ! is_array( $entry ) ) {
178
			$entry = GVCommon::get_entry( $entry );
179
		}
180
181
		$this->entry = $entry;
182
	}
183
184
	/**
185
	 * @return int
186
	 */
187
	public function getPostId() {
0 ignored issues
show
Coding Style introduced by
The function name getPostId is in camel caps, but expected get_post_id instead as per the coding standard.
Loading history...
188
		return $this->post_id;
189
	}
190
191
	/**
192
	 * @param int $post_id
193
	 */
194
	public function setPostId( $post_id ) {
0 ignored issues
show
Coding Style introduced by
The function name setPostId is in camel caps, but expected set_post_id instead as per the coding standard.
Loading history...
195
		$this->post_id = $post_id;
196
	}
197
198
	/**
199
	 * @return boolean
200
	 */
201 2
	public function isPostHasShortcode() {
0 ignored issues
show
Coding Style introduced by
The function name isPostHasShortcode is in camel caps, but expected is_post_has_shortcode instead as per the coding standard.
Loading history...
202 2
		return $this->post_has_shortcode;
203
	}
204
205
	/**
206
	 * @param boolean $post_has_shortcode
207
	 */
208
	public function setPostHasShortcode( $post_has_shortcode ) {
0 ignored issues
show
Coding Style introduced by
The function name setPostHasShortcode is in camel caps, but expected set_post_has_shortcode instead as per the coding standard.
Loading history...
209
		$this->post_has_shortcode = $post_has_shortcode;
210
	}
211
212
	/**
213
	 * @return boolean
214
	 */
215 2
	public function isGravityviewPostType() {
0 ignored issues
show
Coding Style introduced by
The function name isGravityviewPostType is in camel caps, but expected is_gravityview_post_type instead as per the coding standard.
Loading history...
216 2
		return $this->is_gravityview_post_type;
217
	}
218
219
	/**
220
	 * @param boolean $is_gravityview_post_type
221
	 */
222
	public function setIsGravityviewPostType( $is_gravityview_post_type ) {
0 ignored issues
show
Coding Style introduced by
The function name setIsGravityviewPostType is in camel caps, but expected set_is_gravityview_post_type instead as per the coding standard.
Loading history...
223
		$this->is_gravityview_post_type = $is_gravityview_post_type;
224
	}
225
226
	/**
227
	 * Set the context view ID used when page contains multiple embedded views or displaying the single entry view
228
	 *
229
	 *
230
	 *
231
	 * @param null $view_id
232
	 */
233 1
	public function set_context_view_id( $view_id = null ) {
234
235 1
		if ( ! empty( $view_id ) ) {
236
237 1
			$this->context_view_id = $view_id;
238
239 1
		} elseif ( isset( $_GET['gvid'] ) && $this->getGvOutputData()->has_multiple_views() ) {
240
			/**
241
			 * used on a has_multiple_views context
242
			 * @see GravityView_API::entry_link
243
			 * @see GravityView_View_Data::getInstance()->has_multiple_views()
244
			 */
245
			$this->context_view_id = $_GET['gvid'];
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
246
247 1
		} elseif ( ! $this->getGvOutputData()->has_multiple_views() )  {
248 1
			$array_keys = array_keys( $this->getGvOutputData()->get_views() );
249 1
			$this->context_view_id = array_pop( $array_keys );
250 1
			unset( $array_keys );
251
		}
252
253 1
	}
254
255
	/**
256
	 * Returns the the view_id context when page contains multiple embedded views or displaying single entry view
257
	 *
258
	 * @since 1.5.4
259
	 *
260
	 * @return string
261
	 */
262
	public function get_context_view_id() {
263
		return $this->context_view_id;
264
	}
265
266
	/**
267
	 * Allow GravityView entry endpoints on the front page of a site
268
	 *
269
	 * @link  https://core.trac.wordpress.org/ticket/23867 Fixes this core issue
270
	 * @link https://wordpress.org/plugins/cpt-on-front-page/ Code is based on this
271
	 *
272
	 * @since 1.17.3
273
	 *
274
	 * @param WP_Query &$query (passed by reference)
275
	 *
276
	 * @return void
277
	 */
278 4
	public function parse_query_fix_frontpage( &$query ) {
279 4
		global $wp_rewrite;
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...
280
281 4
		$is_front_page = ( $query->is_home || $query->is_page );
282 4
		$show_on_front = ( 'page' === get_option('show_on_front') );
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...
283 4
		$front_page_id = get_option('page_on_front');
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...
284
285 4
		if (  $is_front_page && $show_on_front && $front_page_id ) {
286
287
			// Force to be an array, potentially a query string ( entry=16 )
288
			$_query = wp_parse_args( $query->query );
289
290
			// pagename can be set and empty depending on matched rewrite rules. Ignore an empty pagename.
291
			if ( isset( $_query['pagename'] ) && '' === $_query['pagename'] ) {
292
				unset( $_query['pagename'] );
293
			}
294
295
			// this is where will break from core wordpress
296
			$ignore = array( 'preview', 'page', 'paged', 'cpage' );
297
			$endpoints = rgobj( $wp_rewrite, 'endpoints' );
298
			foreach ( (array) $endpoints as $endpoint ) {
299
				$ignore[] = $endpoint[1];
300
			}
301
			unset( $endpoints );
302
303
			// Modify the query if:
304
			// - We're on the "Page on front" page (which we are), and:
305
			// - The query is empty OR
306
			// - The query includes keys that are associated with registered endpoints. `entry`, for example.
307
			if ( empty( $_query ) || ! array_diff( array_keys( $_query ), $ignore ) ) {
308
309
				$qv =& $query->query_vars;
310
311
				// Prevent redirect when on the single entry endpoint
312
				if( self::is_single_entry() ) {
313
					add_filter( 'redirect_canonical', '__return_false' );
314
				}
315
316
				$query->is_page = true;
317
				$query->is_home = false;
318
				$qv['page_id']  = $front_page_id;
319
320
				// Correct <!--nextpage--> for page_on_front
321
				if ( ! empty( $qv['paged'] ) ) {
322
					$qv['page'] = $qv['paged'];
323
					unset( $qv['paged'] );
324
				}
325
			}
326
327
			// reset the is_singular flag after our updated code above
328
			$query->is_singular = $query->is_single || $query->is_page || $query->is_attachment;
329
		}
330 4
	}
331
332
	/**
333
	 * Read the $post and process the View data inside
334
	 * @param  array  $wp Passed in the `wp` hook. Not used.
335
	 * @return void
336
	 */
337
	public function parse_content( $wp = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $wp 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...
338
		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...
339
340
		// If in admin and NOT AJAX request, get outta here.
341
		if ( function_exists( 'gravityview' ) && gravityview()->request->is_admin() ) {
342
			return;
343
			/** Deprecated in favor of gravityview()->request->is_admin(). */
344
		} else if ( GravityView_Plugin::is_admin() ) {
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_Plugin::is_admin() has been deprecated.

This method has been deprecated.

Loading history...
345
			return;
346
		}
347
348
		// Calculate requested Views
349
		$this->setGvOutputData( GravityView_View_Data::getInstance( $post ) );
350
351
		// !important: we need to run this before getting single entry (to kick the advanced filter)
352
		$this->set_context_view_id();
353
354
		$this->setIsGravityviewPostType( get_post_type( $post ) === 'gravityview' );
355
356
		$post_id = $this->getPostId() ? $this->getPostId() : (isset( $post ) ? $post->ID : null );
357
		$this->setPostId( $post_id );
358
		$post_has_shortcode = ! empty( $post->post_content ) ? gravityview_has_shortcode_r( $post->post_content, 'gravityview' ) : false;
359
		$this->setPostHasShortcode( $this->isGravityviewPostType() ? null : ! empty( $post_has_shortcode ) );
360
361
		// check if the View is showing search results (only for multiple entries View)
362
		$this->setIsSearch( $this->is_searching() );
363
364
		unset( $entry, $post_id, $post_has_shortcode );
365
	}
366
367
	/**
368
	 * Set the entry
369
	 */
370
	function set_entry_data() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
371
		$entry_id = self::is_single_entry();
372
		$this->setSingleEntry( $entry_id );
373
		$this->setEntry( $entry_id );
374
	}
375
376
	/**
377
	 * Checks if the current View is presenting search results
378
	 *
379
	 * @since 1.5.4
380
	 *
381
	 * @return boolean True: Yes, it's a search; False: No, not a search.
382
	 */
383
	function is_searching() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
384
385
		// It's a single entry, not search
386
		if ( $this->getSingleEntry() ) {
387
			return false;
388
		}
389
390
		$search_method = GravityView_Widget_Search::getInstance()->get_search_method();
391
392
		if( 'post' === $search_method ) {
393
			$get = $_POST;
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
394
		} else {
395
			$get = $_GET;
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
396
		}
397
398
		// No $_GET parameters
399
		if ( empty( $get ) || ! is_array( $get ) ) {
400
			return false;
401
		}
402
403
		// Remove empty values
404
		$get = array_filter( $get );
405
406
		// If the $_GET parameters are empty, it's no search.
407
		if ( empty( $get ) ) {
408
			return false;
409
		}
410
411
		$search_keys = array_keys( $get );
412
413
		$search_match = implode( '|', self::$search_parameters );
414
415
		foreach ( $search_keys as $search_key ) {
416
417
			// Analyze the search key $_GET parameter and see if it matches known GV args
418
			if ( preg_match( '/(' . $search_match . ')/i', $search_key ) ) {
419
				return true;
420
			}
421
		}
422
423
		return false;
424
	}
425
426
	/**
427
	 * Filter the title for the single entry view
428
	 *
429
	 * @param  string $title   current title
430
	 * @param  int $passed_post_id Post ID
431
	 * @return string          (modified) title
432
	 */
433
	public function single_entry_title( $title, $passed_post_id = null ) {
434
		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...
435
436
		// If this is the directory view, return.
437
		if ( ! $this->getSingleEntry() ) {
438
			return $title;
439
		}
440
441
		$entry = $this->getEntry();
442
443
		/**
444
		 * @filter `gravityview/single/title/out_loop` Apply the Single Entry Title filter outside the WordPress loop?
445
		 * @param boolean $in_the_loop Whether to apply the filter to the menu title and the meta tag <title> - outside the loop
446
		 * @param array $entry Current entry
447
		 */
448
		$apply_outside_loop = apply_filters( 'gravityview/single/title/out_loop' , in_the_loop(), $entry );
449
450
		if ( ! $apply_outside_loop ) {
451
			return $title;
452
		}
453
454
		// User reported WooCommerce doesn't pass two args.
455
		if ( empty( $passed_post_id ) )  {
456
			return $title;
457
		}
458
459
		// Don't modify the title for anything other than the current view/post.
460
		// This is true for embedded shortcodes and Views.
461
		if ( is_object( $post ) && (int) $post->ID !== (int) $passed_post_id ) {
462
			return $title;
463
		}
464
465
		$context_view_id = $this->get_context_view_id();
466
467
		if ( $this->getGvOutputData()->has_multiple_views() && ! empty( $context_view_id ) ) {
468
			$view_meta = $this->getGvOutputData()->get_view( $context_view_id );
469
		} else {
470
			foreach ( $this->getGvOutputData()->get_views() as $view_id => $view_data ) {
471
				if ( intval( $view_data['form_id'] ) === intval( $entry['form_id'] ) ) {
472
					$view_meta = $view_data;
473
					break;
474
				}
475
			}
476
		}
477
478
		if ( ! empty( $view_meta['atts']['single_title'] ) ) {
479
480
			$title = $view_meta['atts']['single_title'];
481
482
			// We are allowing HTML in the fields, so no escaping the output
483
			$title = GravityView_API::replace_variables( $title, $view_meta['form'], $entry );
484
485
			$title = do_shortcode( $title );
486
		}
487
488
		return $title;
489
	}
490
491
492
	/**
493
	 * In case View post is called directly, insert the view in the post content
494
	 *
495
	 * @access public
496
	 * @static
497
	 * @param mixed $content
498
	 * @return string Add the View output into View CPT content
499
	 */
500
	public function insert_view_in_content( $content ) {
501
502
		// Plugins may run through the content in the header. WP SEO does this for its OpenGraph functionality.
503
		if ( ! did_action( 'loop_start' ) ) {
504
505
			do_action( 'gravityview_log_debug', '[insert_view_in_content] Not processing yet: loop_start hasn\'t run yet. Current action:', current_filter() );
506
507
			return $content;
508
		}
509
510
		//	We don't want this filter to run infinite loop on any post content fields
511
		remove_filter( 'the_content', array( $this, 'insert_view_in_content' ) );
512
513
		// Otherwise, this is called on the Views page when in Excerpt mode.
514
		if ( is_admin() ) {
515
			return $content;
516
		}
517
518
		// Only render in the loop. Fixes issues with the_content filter being applied in places like the sidebar
519
		if( ! in_the_loop() ) {
520
			return $content;
521
		}
522
523
		if ( $this->isGravityviewPostType() ) {
524
525
			/** @since 1.7.4 */
526
			if ( is_preview() && ! gravityview_get_form_id( $this->post_id ) ) {
527
				$content .= __( 'When using a preset template, you must save the View before a Preview is available.', 'gravityview' );
528
			} else {
529
				foreach ( $this->getGvOutputData()->get_views() as $view_id => $data ) {
530
					$content .= $this->render_view( array( 'id' => $view_id ) );
531
				}
532
			}
533
		}
534
535
		//	Add the filter back in
536
		add_filter( 'the_content', array( $this, 'insert_view_in_content' ) );
537
538
		return $content;
539
	}
540
541
	/**
542
	 * Disable comments on GravityView post types
543
	 * @param  boolean $open    existing status
544
	 * @param  int $post_id Post ID
545
	 * @return boolean
546
	 */
547
	public function comments_open( $open, $post_id ) {
548
549
		if ( $this->isGravityviewPostType() ) {
550
			$open = false;
551
		}
552
553
		/**
554
		 * @filter `gravityview/comments_open` Whether to set comments to open or closed.
555
		 * @since  1.5.4
556
		 * @param  boolean $open Open or closed status
557
		 * @param  int $post_id Post ID to set comment status for
558
		 */
559
		$open = apply_filters( 'gravityview/comments_open', $open, $post_id );
560
561
		return $open;
562
	}
563
564
	/**
565
	 * Display a warning when a View has not been configured
566
	 *
567
	 * @since 1.19.2
568
	 *
569
	 * @param int $view_id The ID of the View currently being displayed
570
	 *
571
	 * @return void
572
	 */
573
	public function context_not_configured_warning( $view_id = 0 ) {
574
575
		if ( ! class_exists( 'GravityView_View' ) ) {
576
			return;
577
		}
578
579
		$fields = GravityView_View::getInstance()->getContextFields();
580
581
		if ( ! empty( $fields ) ) {
582
			return;
583
		}
584
585
		$context = GravityView_View::getInstance()->getContext();
586
587
		switch( $context ) {
588
			case 'directory':
589
				$tab = __( 'Multiple Entries', 'gravityview' );
590
				break;
591
			case 'edit':
592
				$tab = __( 'Edit Entry', 'gravityview' );
593
				break;
594
			case 'single':
595
			default:
596
				$tab = __( 'Single Entry', 'gravityview' );
597
				break;
598
		}
599
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
600
601
		$title = sprintf( esc_html_x('The %s layout has not been configured.', 'Displayed when a View is not configured. %s is replaced by the tab label', 'gravityview' ), $tab );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
602
		$edit_link = admin_url( sprintf( 'post.php?post=%d&action=edit#%s-view', $view_id, $context ) );
603
		$action_text = sprintf( esc_html__('Add fields to %s', 'gravityview' ), $tab );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
604
		$message = esc_html__( 'You can only see this message because you are able to edit this View.', 'gravityview' );
605
606
		$output = sprintf( '<h3>%s <strong><a href="%s">%s</a></strong></h3><p>%s</p>', $title, esc_url( $edit_link ), $action_text, $message );
607
608
		echo GVCommon::generate_notice( $output, 'gv-error error', 'edit_gravityview', $view_id );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'GVCommon'
Loading history...
609
	}
610
611
612
	/**
613
	 * Core function to render a View based on a set of arguments
614
	 *
615
	 * @access public
616
	 * @static
617
	 * @param array $passed_args {
618
	 *
619
	 *      Settings for rendering the View
620
	 *
621
	 *      @type int $id View id
622
	 *      @type int $page_size Number of entries to show per page
623
	 *      @type string $sort_field Form field id to sort
624
	 *      @type string $sort_direction Sorting direction ('ASC' or 'DESC')
625
	 *      @type string $start_date - Ymd
626
	 *      @type string $end_date - Ymd
627
	 *      @type string $class - assign a html class to the view
628
	 *      @type string $offset (optional) - This is the start point in the current data set (0 index based).
629
	 * }
630
	 *
631
	 * @return string|null HTML output of a View, NULL if View isn't found
632
	 */
633
	public function render_view( $passed_args ) {
634
635
		// validate attributes
636
		if ( empty( $passed_args['id'] ) ) {
637
			do_action( 'gravityview_log_error', '[render_view] Returning; no ID defined.', $passed_args );
638
			return null;
639
		}
640
641
		// Solve problem when loading content via admin-ajax.php
642
		// @hack
643
		if ( ! $this->getGvOutputData() ) {
644
645
			do_action( 'gravityview_log_error', '[render_view] gv_output_data not defined; parsing content.', $passed_args );
646
647
			$this->parse_content();
648
		}
649
650
		// Make 100% sure that we're dealing with a properly called situation
651
		if ( ! is_object( $this->getGvOutputData() ) || ! is_callable( array( $this->getGvOutputData(), 'get_view' ) ) ) {
652
653
			do_action( 'gravityview_log_error', '[render_view] gv_output_data not an object or get_view not callable.', $this->getGvOutputData() );
654
655
			return null;
656
		}
657
658
		$view_id = $passed_args['id'];
659
660
		$view_data = $this->getGvOutputData()->get_view( $view_id, $passed_args );
661
662
		do_action( 'gravityview_log_debug', '[render_view] View Data: ', $view_data );
663
664
		do_action( 'gravityview_log_debug', '[render_view] Init View. Arguments: ', $passed_args );
665
666
		// The passed args were always winning, even if they were NULL.
667
		// This prevents that. Filters NULL, FALSE, and empty strings.
668
		$passed_args = array_filter( $passed_args, 'strlen' );
669
670
		//Override shortcode args over View template settings
671
		$atts = wp_parse_args( $passed_args, $view_data['atts'] );
672
673
		do_action( 'gravityview_log_debug', '[render_view] Arguments after merging with View settings: ', $atts );
674
675
		// It's password protected and you need to log in.
676
		if ( post_password_required( $view_id ) ) {
677
678
			do_action( 'gravityview_log_error', sprintf( '[render_view] Returning: View %d is password protected.', $view_id ) );
679
680
			// If we're in an embed or on an archive page, show the password form
681
			if ( get_the_ID() !== $view_id ) {
682
				return get_the_password_form();
683
			}
684
685
			// Otherwise, just get outta here
686
			return null;
687
		}
688
689
		/**
690
		 * Don't render View if user isn't allowed to see it
691
		 * @since 1.15
692
		 * @since 1.17.2 Added check for if a user has no caps but is logged in (member of multisite, but not any site). Treat as if logged-out.
693
		 */
694
		if( is_user_logged_in() && ! ( empty( wp_get_current_user()->caps ) && empty( wp_get_current_user()->roles ) ) && false === GVCommon::has_cap( 'read_gravityview', $view_id ) ) {
695
696
			do_action( 'gravityview_log_debug', sprintf( '%s Returning: View %d is not visible by current user.', __METHOD__, $view_id ) );
697
698
			return null;
699
		}
700
701
		if( $this->isGravityviewPostType() ) {
702
703
			/**
704
			 * @filter `gravityview_direct_access` Should Views be directly accessible, or only visible using the shortcode?
705
			 * @see https://codex.wordpress.org/Function_Reference/register_post_type#public
706
			 * @see \GV\Entry::get_endpoint_name
707
			 * @since 1.15.2
708
			 * @param[in,out] boolean `true`: allow Views to be accessible directly. `false`: Only allow Views to be embedded via shortcode. Default: `true`
709
			 * @param int $view_id The ID of the View currently being requested. `0` for general setting
710
			 */
711
			$direct_access = apply_filters( 'gravityview_direct_access', true, $view_id );
712
713
			$embed_only = ! empty( $atts['embed_only'] );
714
715
			if( ! $direct_access || ( $embed_only && ! GVCommon::has_cap( 'read_private_gravityviews' ) ) ) {
716
				return __( 'You are not allowed to view this content.', 'gravityview' );
717
			}
718
		}
719
720
		ob_start();
721
722
		/**
723
		 * Set globals for templating
724
		 * @deprecated 1.6.2
725
		 */
726
		global $gravityview_view;
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...
727
728
		$gravityview_view = new GravityView_View( $view_data );
729
730
		$post_id = ! empty( $atts['post_id'] ) ? intval( $atts['post_id'] ) : get_the_ID();
731
732
		$gravityview_view->setPostId( $post_id );
733
734
		if ( ! $this->getSingleEntry() ) {
735
736
			// user requested Directory View
737
			do_action( 'gravityview_log_debug', '[render_view] Executing Directory View' );
738
739
			//fetch template and slug
740
			$view_slug = apply_filters( 'gravityview_template_slug_'. $view_data['template_id'], 'table', 'directory' );
741
742
			do_action( 'gravityview_log_debug', '[render_view] View template slug: ', $view_slug );
743
744
			/**
745
			 * Disable fetching initial entries for views that don't need it (DataTables)
746
			 */
747
			$get_entries = apply_filters( 'gravityview_get_view_entries_'.$view_slug, true );
748
749
			/**
750
			 * Hide View data until search is performed
751
			 * @since 1.5.4
752
			 */
753
			if ( ! empty( $atts['hide_until_searched'] ) && ! $this->isSearch() ) {
754
				$gravityview_view->setHideUntilSearched( true );
755
				$get_entries = false;
756
			}
757
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
758
759
			if ( $get_entries ) {
760
761
				if ( ! empty( $atts['sort_columns'] ) ) {
762
					// add filter to enable column sorting
763
					add_filter( 'gravityview/template/field_label', array( $this, 'add_columns_sort_links' ) , 100, 3 );
764
				}
765
766
				$view_entries = self::get_view_entries( $atts, $view_data['form_id'] );
767
768
				do_action( 'gravityview_log_debug', sprintf( '[render_view] Get Entries. Found %s entries total, showing %d entries', $view_entries['count'], sizeof( $view_entries['entries'] ) ) );
769
770
			} else {
771
772
				$view_entries = array( 'count' => null, 'entries' => null, 'paging' => null );
773
774
				do_action( 'gravityview_log_debug', '[render_view] Not fetching entries because `gravityview_get_view_entries_'.$view_slug.'` is false' );
775
			}
776
777
			$gravityview_view->setPaging( $view_entries['paging'] );
778
			$gravityview_view->setContext( 'directory' );
779
			$sections = array( 'header', 'body', 'footer' );
780
781
		} else {
782
783
			// user requested Single Entry View
784
			do_action( 'gravityview_log_debug', '[render_view] Executing Single View' );
785
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
786
787
			/**
788
			 * @action `gravityview_render_entry_{View ID}` Before rendering a single entry for a specific View ID
789
			 * @since 1.17
790
			 */
791
			do_action( 'gravityview_render_entry_'.$view_data['id'] );
792
793
			$entry = $this->getEntry();
794
795
			// You are not permitted to view this entry.
796
			if ( empty( $entry ) || ! self::is_entry_approved( $entry, $atts ) ) {
797
798
				do_action( 'gravityview_log_debug', '[render_view] Entry does not exist. This may be because of View filters limiting access.' );
799
800
				// Only display warning once when multiple Views are embedded
801
				if( $view_id !== (int) GravityView_frontend::get_context_view_id() ) {
802
					ob_end_clean();
803
					return null;
804
				}
805
806
				/**
807
				 * @filter `gravityview/render/entry/not_visible` Modify the message shown to users when the entry doesn't exist or they aren't allowed to view it.
808
				 * @since 1.6
809
				 * @param string $message Default: "You have attempted to view an entry that is not visible or may not exist."
810
				 */
811
				$message = apply_filters( 'gravityview/render/entry/not_visible', __( 'You have attempted to view an entry that is not visible or may not exist.', 'gravityview' ) );
812
813
				/**
814
				 * @since 1.6
815
				 */
816
				echo esc_attr( $message );
817
818
				ob_end_clean();
819
				return null;
820
			}
821
822
			// We're in single view, but the view being processed is not the same view the single entry belongs to.
823
			// important: do not remove this as it prevents fake attempts of displaying entries from other views/forms
824
			if ( $this->getGvOutputData()->has_multiple_views() && $view_id != $this->get_context_view_id() ) {
825
				do_action( 'gravityview_log_debug', '[render_view] In single entry view, but the entry does not belong to this View. Perhaps there are multiple views on the page. View ID: '. $view_id );
826
				ob_end_clean();
827
				return null;
828
			}
829
830
			//fetch template and slug
831
			$view_slug = apply_filters( 'gravityview_template_slug_' . $view_data['template_id'], 'table', 'single' );
832
			do_action( 'gravityview_log_debug', '[render_view] View single template slug: ', $view_slug );
833
834
			//fetch entry detail
835
			$view_entries['count'] = 1;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$view_entries was never initialized. Although not strictly required by PHP, it is generally a good practice to add $view_entries = 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...
836
			$view_entries['entries'][] = $entry;
837
			do_action( 'gravityview_log_debug', '[render_view] Get single entry: ', $view_entries['entries'] );
838
839
			$back_link_label = isset( $atts['back_link_label'] ) ? $atts['back_link_label'] : null;
840
841
			// set back link label
842
			$gravityview_view->setBackLinkLabel( $back_link_label );
843
			$gravityview_view->setContext( 'single' );
844
			$sections = array( 'single' );
845
846
		}
847
848
		// add template style
849
		self::add_style( $view_data['template_id'] );
850
851
		// Prepare to render view and set vars
852
		$gravityview_view->setEntries( $view_entries['entries'] );
853
		$gravityview_view->setTotalEntries( $view_entries['count'] );
854
855
		// If Edit
856
		if ( 'edit' === gravityview_get_context() ) {
857
858
			do_action( 'gravityview_log_debug', '[render_view] Edit Entry ' );
859
860
			do_action( 'gravityview_edit_entry', $this->getGvOutputData() );
861
862
			return ob_get_clean();
863
864
		} else {
865
			// finaly we'll render some html
866
			$sections = apply_filters( 'gravityview_render_view_sections', $sections, $view_data['template_id'] );
867
868
			do_action( 'gravityview_log_debug', '[render_view] Sections to render: ', $sections );
869
			foreach ( $sections as $section ) {
870
				do_action( 'gravityview_log_debug', '[render_view] Rendering '. $section . ' section.' );
871
				$gravityview_view->render( $view_slug, $section, false );
872
			}
873
		}
874
875
		//@todo: check why we need the IF statement vs. print the view id always.
876
		if ( $this->isGravityviewPostType() || $this->isPostHasShortcode() ) {
877
			// Print the View ID to enable proper cookie pagination
878
			echo '<input type="hidden" class="gravityview-view-id" value="' . esc_attr( $view_id ) . '">';
879
		}
880
		$output = ob_get_clean();
881
882
		return $output;
883
	}
884
885
	/**
886
	 * Process the start and end dates for a view - overrides values defined in shortcode (if needed)
887
	 *
888
	 * The `start_date` and `end_date` keys need to be in a format processable by GFFormsModel::get_date_range_where(),
889
	 * which uses \DateTime() format.
890
	 *
891
	 * You can set the `start_date` or `end_date` to any value allowed by {@link http://www.php.net//manual/en/function.strtotime.php strtotime()},
892
	 * including strings like "now" or "-1 year" or "-3 days".
893
	 *
894
	 * @see GFFormsModel::get_date_range_where
895
	 *
896
	 * @param  array      $args            View settings
897
	 * @param  array      $search_criteria Search being performed, if any
898
	 * @return array                       Modified `$search_criteria` array
899
	 */
900 1
	public static function process_search_dates( $args, $search_criteria = array() ) {
901
902 1
		$return_search_criteria = $search_criteria;
903
904 1
		foreach ( array( 'start_date', 'end_date' ) as $key ) {
905
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
906
907
			// Is the start date or end date set in the view or shortcode?
908
			// If so, we want to make sure that the search doesn't go outside the bounds defined.
909 1
			if ( ! empty( $args[ $key ] ) ) {
910
911
				// Get a timestamp and see if it's a valid date format
912 1
				$date = strtotime( $args[ $key ] );
913
914
				// The date was invalid
915 1
				if ( empty( $date ) ) {
916
					do_action( 'gravityview_log_error', __METHOD__ . ' Invalid ' . $key . ' date format: ' . $args[ $key ] );
917
					continue;
918
				}
919
920
				// The format that Gravity Forms expects for start_date and day-specific (not hour/second-specific) end_date
921 1
				$datetime_format = 'Y-m-d H:i:s';
922 1
				$search_is_outside_view_bounds = false;
923
924 1
				if( ! empty( $search_criteria[ $key ] ) ) {
925
926 1
					$search_date = strtotime( $search_criteria[ $key ] );
927
928
					// The search is for entries before the start date defined by the settings
929
					switch ( $key ) {
930 1
						case 'end_date':
931
							/**
932
							 * If the end date is formatted as 'Y-m-d', it should be formatted without hours and seconds
933
							 * so that Gravity Forms can convert the day to 23:59:59 the previous day.
934
							 *
935
							 * If it's a relative date ("now" or "-1 day"), then it should use the precise date format
936
							 *
937
							 * @see GFFormsModel::get_date_range_where
938
							 */
939 1
							$datetime_format               = gravityview_is_valid_datetime( $args[ $key ] ) ? 'Y-m-d' : 'Y-m-d H:i:s';
940 1
							$search_is_outside_view_bounds = ( $search_date > $date );
941 1
							break;
942 1
						case 'start_date':
943 1
							$search_is_outside_view_bounds = ( $search_date < $date );
944 1
							break;
945
					}
946
				}
947
948
				// If there is no search being performed, or if there is a search being performed that's outside the bounds
949 1
				if ( empty( $search_criteria[ $key ] ) || $search_is_outside_view_bounds ) {
950
951
					// Then we override the search and re-set the start date
952 1
					$return_search_criteria[ $key ] = date_i18n( $datetime_format , $date, true );
953
				}
954
			}
955
		}
956
957 1
		if( isset( $return_search_criteria['start_date'] ) && isset( $return_search_criteria['end_date'] ) ) {
958
			// The start date is AFTER the end date. This will result in no results, but let's not force the issue.
959 1
			if ( strtotime( $return_search_criteria['start_date'] ) > strtotime( $return_search_criteria['end_date'] ) ) {
960 1
				do_action( 'gravityview_log_error', __METHOD__ . ' Invalid search: the start date is after the end date.', $return_search_criteria );
961
			}
962
		}
963
964 1
		return $return_search_criteria;
965
	}
966
967
968
	/**
969
	 * Process the approved only search criteria according to the View settings
970
	 *
971
	 * @param  array      $args            View settings
972
	 * @param  array      $search_criteria Search being performed, if any
973
	 * @return array                       Modified `$search_criteria` array
974
	 */
975
	public static function process_search_only_approved( $args, $search_criteria ) {
976
977
		/** @since 1.19 */
978
		if( ! empty( $args['admin_show_all_statuses'] ) && GVCommon::has_cap('gravityview_moderate_entries') ) {
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...
979
			do_action( 'gravityview_log_debug', __METHOD__ . ': User can moderate entries; showing all approval statuses' );
980
			return $search_criteria;
981
		}
982
983
		if ( ! empty( $args['show_only_approved'] ) ) {
984
985
			$search_criteria['field_filters'][] = array(
986
				'key' => GravityView_Entry_Approval::meta_key,
987
				'value' => GravityView_Entry_Approval_Status::APPROVED
0 ignored issues
show
introduced by
Each line in an array declaration must end in a comma
Loading history...
988
			);
989
990
			$search_criteria['field_filters']['mode'] = 'all'; // force all the criterias to be met
991
992
			do_action( 'gravityview_log_debug', '[process_search_only_approved] Search Criteria if show only approved: ', $search_criteria );
993
		}
994
995
		return $search_criteria;
996
	}
997
998
999
	/**
1000
	 * Check if a certain entry is approved.
1001
	 *
1002
	 * If we pass the View settings ($args) it will check the 'show_only_approved' setting before
1003
	 *   checking the entry approved field, returning true if show_only_approved = false.
1004
	 *
1005
	 * @since 1.7
1006
	 * @since 1.18 Converted check to use GravityView_Entry_Approval_Status::is_approved
1007
	 *
1008
	 * @uses GravityView_Entry_Approval_Status::is_approved
1009
	 *
1010
	 * @param array $entry  Entry object
1011
	 * @param array $args   View settings (optional)
1012
	 *
1013
	 * @return bool
1014
	 */
1015
	public static function is_entry_approved( $entry, $args = array() ) {
1016
1017
		if ( empty( $entry['id'] ) || ( array_key_exists( 'show_only_approved', $args ) && ! $args['show_only_approved'] ) ) {
1018
			// is implicitly approved if entry is null or View settings doesn't require to check for approval
1019
			return true;
1020
		}
1021
1022
		/** @since 1.19 */
1023
		if( ! empty( $args['admin_show_all_statuses'] ) && GVCommon::has_cap('gravityview_moderate_entries') ) {
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...
1024
			do_action( 'gravityview_log_debug', __METHOD__ . ': User can moderate entries, so entry is approved for viewing' );
1025
			return true;
1026
		}
1027
1028
		$is_approved = gform_get_meta( $entry['id'], GravityView_Entry_Approval::meta_key );
1029
1030
		return GravityView_Entry_Approval_Status::is_approved( $is_approved );
1031
	}
1032
1033
	/**
1034
	 * Parse search criteria for a entries search.
1035
	 *
1036
	 * array(
1037
	 * 	'search_field' => 1, // ID of the field
1038
	 *  'search_value' => '', // Value of the field to search
1039
	 *  'search_operator' => 'contains', // 'is', 'isnot', '>', '<', 'contains'
1040
	 *  'show_only_approved' => 0 or 1 // Boolean
1041
	 * )
1042
	 *
1043
	 * @param  array $args    Array of args
1044
	 * @param  int $form_id Gravity Forms form ID
1045
	 * @return array          Array of search parameters, formatted in Gravity Forms mode, using `status` key set to "active" by default, `field_filters` array with `key`, `value` and `operator` keys.
1046
	 */
1047
	public static function get_search_criteria( $args, $form_id ) {
1048
1049
		/**
1050
		 * @filter `gravityview_fe_search_criteria` Modify the search criteria
1051
		 * @see GravityView_Widget_Search::filter_entries Adds the default search criteria
1052
		 * @param array $search_criteria Empty `field_filters` key
1053
		 * @param int $form_id ID of the Gravity Forms form that is being searched
1054
		 */
1055
		$search_criteria = apply_filters( 'gravityview_fe_search_criteria', array( 'field_filters' => array() ), $form_id );
1056
1057
		$original_search_criteria = $search_criteria;
1058
1059
		do_action( 'gravityview_log_debug', '[get_search_criteria] Search Criteria after hook gravityview_fe_search_criteria: ', $search_criteria );
1060
1061
		// implicity search
1062
		if ( ! empty( $args['search_value'] ) ) {
1063
1064
			// Search operator options. Options: `is` or `contains`
1065
			$operator = ! empty( $args['search_operator'] ) && in_array( $args['search_operator'], array( 'is', 'isnot', '>', '<', 'contains' ) ) ? $args['search_operator'] : 'contains';
1066
1067
			$search_criteria['field_filters'][] = array(
1068
				'key' => rgget( 'search_field', $args ), // The field ID to search
1069
				'value' => _wp_specialchars( $args['search_value'] ), // The value to search. Encode ampersands but not quotes.
1070
				'operator' => $operator,
1071
			);
1072
		}
1073
1074
		if( $search_criteria !== $original_search_criteria ) {
1075
			do_action( 'gravityview_log_debug', '[get_search_criteria] Search Criteria after implicity search: ', $search_criteria );
1076
		}
1077
1078
		// Handle setting date range
1079
		$search_criteria = self::process_search_dates( $args, $search_criteria );
1080
1081
		if( $search_criteria !== $original_search_criteria ) {
1082
			do_action( 'gravityview_log_debug', '[get_search_criteria] Search Criteria after date params: ', $search_criteria );
1083
		}
1084
1085
		// remove not approved entries
1086
		$search_criteria = self::process_search_only_approved( $args, $search_criteria );
1087
1088
		/**
1089
		 * @filter `gravityview_status` Modify entry status requirements to be included in search results.
1090
		 * @param string $status Default: `active`. Accepts all Gravity Forms entry statuses, including `spam` and `trash`
1091
		 */
1092
		$search_criteria['status'] = apply_filters( 'gravityview_status', 'active', $args );
1093
1094
		return $search_criteria;
1095
	}
1096
1097
1098
1099
	/**
1100
	 * Core function to calculate View multi entries (directory) based on a set of arguments ($args):
1101
	 *   $id - View id
1102
	 *   $page_size - Page
1103
	 *   $sort_field - form field id to sort
1104
	 *   $sort_direction - ASC / DESC
1105
	 *   $start_date - Ymd
1106
	 *   $end_date - Ymd
1107
	 *   $class - assign a html class to the view
1108
	 *   $offset (optional) - This is the start point in the current data set (0 index based).
1109
	 *
1110
	 *
1111
	 *
1112
	 * @uses  gravityview_get_entries()
1113
	 * @access public
1114
	 * @param array $args\n
0 ignored issues
show
Bug introduced by
There is no parameter named $args\n. 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...
1115
	 *   - $id - View id
1116
	 *   - $page_size - Page
1117
	 *   - $sort_field - form field id to sort
1118
	 *   - $sort_direction - ASC / DESC
1119
	 *   - $start_date - Ymd
1120
	 *   - $end_date - Ymd
1121
	 *   - $class - assign a html class to the view
1122
	 *   - $offset (optional) - This is the start point in the current data set (0 index based).
1123
	 * @param int $form_id Gravity Forms Form ID
1124
	 * @return array Associative array with `count`, `entries`, and `paging` keys. `count` has the total entries count, `entries` is an array with Gravity Forms full entry data, `paging` is an array with `offset` and `page_size` keys
1125
	 */
1126
	public static function get_view_entries( $args, $form_id ) {
1127
1128
		do_action( 'gravityview_log_debug', '[get_view_entries] init' );
1129
		// start filters and sorting
1130
1131
		$parameters = self::get_view_entries_parameters( $args, $form_id );
1132
1133
		$count = 0; // Must be defined so that gravityview_get_entries can use by reference
1134
1135
		//fetch entries
1136
		$entries = gravityview_get_entries( $form_id, $parameters, $count );
1137
1138
		do_action( 'gravityview_log_debug', sprintf( '%s: Get Entries. Found: %s entries', __METHOD__, $count ), $entries );
1139
1140
		/**
1141
		 * @filter `gravityview_view_entries` Filter the entries output to the View
1142
		 * @deprecated since 1.5.2
1143
		 * @param array $args View settings associative array
1144
		 * @var array
1145
		 */
1146
		$entries = apply_filters( 'gravityview_view_entries', $entries, $args );
1147
1148
		$return = array(
1149
			'count' => $count,
1150
			'entries' => $entries,
1151
			'paging' => rgar( $parameters, 'paging' ),
1152
		);
1153
1154
		/**
1155
		 * @filter `gravityview/view/entries` Filter the entries output to the View
1156
		 * @param array $criteria associative array containing count, entries & paging
1157
		 * @param array $args View settings associative array
1158
		 * @since 1.5.2
1159
		 */
1160
		return apply_filters( 'gravityview/view/entries', $return, $args );
1161
	}
1162
1163
	/**
1164
	 * Get an array of search parameters formatted as Gravity Forms requires
1165
	 *
1166
	 * Results are filtered by `gravityview_get_entries` and `gravityview_get_entries_{View ID}` filters
1167
	 *
1168
	 * @uses GravityView_frontend::get_search_criteria
1169
	 * @uses GravityView_frontend::get_search_criteria_paging
1170
	 *
1171
	 * @since 1.20
1172
	 *
1173
	 * @see GravityView_View_Data::get_default_args For $args options
1174
	 *
1175
	 * @param array $args Array of View settings, as structured in GravityView_View_Data::get_default_args
1176
	 * @param int $form_id Gravity Forms form ID to search
1177
	 *
1178
	 * @return array With `search_criteria`, `sorting`, `paging`, `cache` keys
1179
	 */
1180
	public static function get_view_entries_parameters( $args = array(), $form_id = 0 ) {
1181
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1182
1183
		if ( ! is_array( $args ) || ! is_numeric( $form_id ) ) {
1184
1185
			do_action( 'gravityview_log_error', __METHOD__ . ': Passed args are not an array or the form ID is not numeric' );
1186
1187
			return array();
1188
		}
1189
1190
		$form_id = intval( $form_id );
1191
1192
		/**
1193
		 * Process search parameters
1194
		 * @var array
1195
		 */
1196
		$search_criteria = self::get_search_criteria( $args, $form_id );
1197
1198
		$paging = self::get_search_criteria_paging( $args );
1199
1200
		$parameters = array(
1201
			'search_criteria' => $search_criteria,
1202
			'sorting' => self::updateViewSorting( $args, $form_id ),
1203
			'paging' => $paging,
1204
			'cache' => isset( $args['cache'] ) ? $args['cache'] : true,
1205
		);
1206
1207
		/**
1208
		 * @filter `gravityview_get_entries` Filter get entries criteria
1209
		 * @param array $parameters Array with `search_criteria`, `sorting` and `paging` keys.
1210
		 * @param array $args View configuration args. {
1211
		 *      @type int $id View id
1212
		 *      @type int $page_size Number of entries to show per page
1213
		 *      @type string $sort_field Form field id to sort
1214
		 *      @type string $sort_direction Sorting direction ('ASC' or 'DESC')
1215
		 *      @type string $start_date - Ymd
1216
		 *      @type string $end_date - Ymd
1217
		 *      @type string $class - assign a html class to the view
1218
		 *      @type string $offset (optional) - This is the start point in the current data set (0 index based).
1219
		 * }
1220
		 * @param int $form_id ID of Gravity Forms form
1221
		 */
1222
		$parameters = apply_filters( 'gravityview_get_entries', $parameters, $args, $form_id );
1223
1224
		/**
1225
		 * @filter `gravityview_get_entries_{View ID}` Filter get entries criteria
1226
		 * @param array $parameters Array with `search_criteria`, `sorting` and `paging` keys.
1227
		 * @param array $args View configuration args.
1228
		 */
1229
		$parameters = apply_filters( 'gravityview_get_entries_'.$args['id'], $parameters, $args, $form_id );
1230
1231
		do_action( 'gravityview_log_debug', __METHOD__ . ': $parameters passed to gravityview_get_entries(): ', $parameters );
1232
1233
		return $parameters;
1234
	}
1235
1236
	/**
1237
	 * Get the paging array for the View
1238
	 *
1239
	 * @since 1.19.5
1240
	 *
1241
	 * @param $args
1242
	 * @param int $form_id
0 ignored issues
show
Bug introduced by
There is no parameter named $form_id. 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...
1243
	 */
1244
	public static function get_search_criteria_paging( $args ) {
1245
1246
		/**
1247
		 * @filter `gravityview_default_page_size` The default number of entries displayed in a View
1248
		 * @since 1.1.6
1249
		 * @param int $default_page_size Default: 25
1250
		 */
1251
		$default_page_size = apply_filters( 'gravityview_default_page_size', 25 );
1252
1253
		// Paging & offset
1254
		$page_size = ! empty( $args['page_size'] ) ? intval( $args['page_size'] ) : $default_page_size;
1255
1256
		if ( -1 === $page_size ) {
1257
			$page_size = PHP_INT_MAX;
1258
		}
1259
1260
		$curr_page = empty( $_GET['pagenum'] ) ? 1 : intval( $_GET['pagenum'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
1261
		$offset = ( $curr_page - 1 ) * $page_size;
1262
1263
		if ( ! empty( $args['offset'] ) ) {
1264
			$offset += intval( $args['offset'] );
1265
		}
1266
1267
		$paging = array(
1268
			'offset' => $offset,
1269
			'page_size' => $page_size,
1270
		);
1271
1272
		do_action( 'gravityview_log_debug', __METHOD__ . ': Paging: ', $paging );
1273
1274
		return $paging;
1275
	}
1276
1277
	/**
1278
	 * Updates the View sorting criteria
1279
	 *
1280
	 * @since 1.7
1281
	 *
1282
	 * @param array $args View settings. Required to have `sort_field` and `sort_direction` keys
1283
	 * @param int $form_id The ID of the form used to sort
1284
	 * @return array $sorting Array with `key`, `direction` and `is_numeric` keys
1285
	 */
1286
	public static function updateViewSorting( $args, $form_id ) {
0 ignored issues
show
Coding Style introduced by
The function name updateViewSorting is in camel caps, but expected update_view_sorting instead as per the coding standard.
Loading history...
1287
		$sorting = array();
1288
		$sort_field_id = isset( $_GET['sort'] ) ? $_GET['sort'] : rgar( $args, 'sort_field' );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
1289
		$sort_direction = isset( $_GET['dir'] ) ? $_GET['dir'] : rgar( $args, 'sort_direction' );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
1290
1291
		$sort_field_id = self::_override_sorting_id_by_field_type( $sort_field_id, $form_id );
1292
1293
		if ( ! empty( $sort_field_id ) ) {
1294
			$sorting = array(
1295
				'key' => $sort_field_id,
1296
				'direction' => strtolower( $sort_direction ),
1297
				'is_numeric' => GVCommon::is_field_numeric( $form_id, $sort_field_id )
1298
			);
1299
		}
1300
1301
		GravityView_View::getInstance()->setSorting( $sorting );
1302
1303
		do_action( 'gravityview_log_debug', '[updateViewSorting] Sort Criteria : ', $sorting );
1304
1305
		return $sorting;
1306
1307
	}
1308
1309
	/**
1310
	 * Override sorting per field
1311
	 *
1312
	 * Currently only modifies sorting ID when sorting by the full name. Sorts by first name.
1313
	 * Use the `gravityview/sorting/full-name` filter to override.
1314
	 *
1315
	 * @todo Filter from GravityView_Field
1316
	 * @since 1.7.4
1317
	 *
1318
	 * @param int|string $sort_field_id Field used for sorting (`id` or `1.2`)
1319
	 * @param int $form_id GF Form ID
1320
	 *
1321
	 * @return string Possibly modified sorting ID
1322
	 */
1323
	private static function _override_sorting_id_by_field_type( $sort_field_id, $form_id ) {
1324
1325
		$form = gravityview_get_form( $form_id );
1326
1327
		$sort_field = GFFormsModel::get_field( $form, $sort_field_id );
1328
1329
		if( ! $sort_field ) {
1330
			return $sort_field_id;
1331
		}
1332
1333
		switch ( $sort_field['type'] ) {
1334
1335
			case 'address':
1336
				// Sorting by full address
1337
				if ( floatval( $sort_field_id ) === floor( $sort_field_id ) ) {
1338
1339
					/**
1340
					 * Override how to sort when sorting address
1341
					 *
1342
					 * @since 1.8
1343
					 *
1344
					 * @param string $address_part `street`, `street2`, `city`, `state`, `zip`, or `country` (default: `city`)
1345
					 * @param string $sort_field_id Field used for sorting
1346
					 * @param int $form_id GF Form ID
1347
					 */
1348
					$address_part = apply_filters( 'gravityview/sorting/address', 'city', $sort_field_id, $form_id );
1349
1350
					switch( strtolower( $address_part ) ){
1351
						case 'street':
1352
							$sort_field_id .= '.1';
1353
							break;
1354
						case 'street2':
1355
							$sort_field_id .= '.2';
1356
							break;
1357
						default:
1358
						case 'city':
0 ignored issues
show
Unused Code introduced by
case 'city': $sort_f..._id .= '.3'; break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1359
							$sort_field_id .= '.3';
1360
							break;
1361
						case 'state':
1362
							$sort_field_id .= '.4';
1363
							break;
1364
						case 'zip':
1365
							$sort_field_id .= '.5';
1366
							break;
1367
						case 'country':
1368
							$sort_field_id .= '.6';
1369
							break;
1370
					}
1371
1372
				}
1373
				break;
1374
			case 'name':
1375
				// Sorting by full name, not first, last, etc.
1376
				if ( floatval( $sort_field_id ) === floor( $sort_field_id ) ) {
1377
					/**
1378
					 * @filter `gravityview/sorting/full-name` Override how to sort when sorting full name.
1379
					 * @since 1.7.4
1380
					 * @param[in,out] string $name_part Sort by `first` or `last` (default: `first`)
1381
					 * @param[in] string $sort_field_id Field used for sorting
1382
					 * @param[in] int $form_id GF Form ID
1383
					 */
1384
					$name_part = apply_filters( 'gravityview/sorting/full-name', 'first', $sort_field_id, $form_id );
1385
1386
					if ( 'last' === strtolower( $name_part ) ) {
1387
						$sort_field_id .= '.6';
1388
					} else {
1389
						$sort_field_id .= '.3';
1390
					}
1391
				}
1392
				break;
1393
			case 'list':
1394
				$sort_field_id = false;
1395
				break;
1396
			case 'time':
1397
1398
				/**
1399
				 * @filter `gravityview/sorting/time` Override how to sort when sorting time
1400
				 * @see GravityView_Field_Time
1401
				 * @since 1.14
1402
				 * @param[in,out] string $name_part Field used for sorting
1403
				 * @param[in] int $form_id GF Form ID
1404
				 */
1405
				$sort_field_id = apply_filters( 'gravityview/sorting/time', $sort_field_id, $form_id );
1406
				break;
1407
		}
1408
1409
		return $sort_field_id;
1410
	}
1411
1412
	/**
1413
	 * Verify if user requested a single entry view
1414
	 * @return boolean|string false if not, single entry slug if true
1415
	 */
1416 2
	public static function is_single_entry() {
1417
1418 2
		if ( function_exists( 'gravityview' ) ) {
1419 2
			$var_name = \GV\Entry::get_endpoint_name();
1420
		} else {
1421
			/** Deprecated. Use \GV\Entry::get_endpoint_name instead. */
1422
			$var_name = GravityView_Post_Types::get_entry_var_name();
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_Post_Types::get_entry_var_name() has been deprecated.

This method has been deprecated.

Loading history...
1423
		}
1424
1425 2
		$single_entry = get_query_var( $var_name );
1426
1427
		/**
1428
		 * Modify the entry that is being displayed.
1429
		 *
1430
		 * @internal Should only be used by things like the oEmbed functionality.
1431
		 * @since 1.6
1432
		 */
1433 2
		$single_entry = apply_filters( 'gravityview/is_single_entry', $single_entry );
1434
1435 2
		if ( empty( $single_entry ) ){
1436
			return false;
1437
		} else {
1438 2
			return $single_entry;
1439
		}
1440
	}
1441
1442
1443
	/**
1444
	 * Register styles and scripts
1445
	 *
1446
	 * @access public
1447
	 * @return void
1448
	 */
1449
	public function add_scripts_and_styles() {
1450
		global $post, $posts;
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...
1451
		// enqueue template specific styles
1452
		if ( $this->getGvOutputData() ) {
1453
1454
			$views = $this->getGvOutputData()->get_views();
1455
1456
			foreach ( $views as $view_id => $data ) {
1457
1458
				/**
1459
				 * Don't enqueue the scripts or styles if it's not going to be displayed.
1460
				 * @since 1.15
1461
				 */
1462
				if( is_user_logged_in() && false === GVCommon::has_cap( 'read_gravityview', $view_id ) ) {
1463
					continue;
1464
				}
1465
1466
				// By default, no thickbox
1467
				$js_dependencies = array( 'jquery', 'gravityview-jquery-cookie' );
1468
				$css_dependencies = array();
1469
1470
				// If the thickbox is enqueued, add dependencies
1471
				if ( ! empty( $data['atts']['lightbox'] ) ) {
1472
1473
					/**
1474
					 * @filter `gravity_view_lightbox_script` Override the lightbox script to enqueue. Default: `thickbox`
1475
					 * @param string $script_slug If you want to use a different lightbox script, return the name of it here.
1476
					 */
1477
					$js_dependencies[] = apply_filters( 'gravity_view_lightbox_script', 'thickbox' );
1478
1479
					/**
1480
					 * @filter `gravity_view_lightbox_style` Modify the lightbox CSS slug. Default: `thickbox`
1481
					 * @param string $script_slug If you want to use a different lightbox script, return the name of its CSS file here.
1482
					 */
1483
					$css_dependencies[] = apply_filters( 'gravity_view_lightbox_style', 'thickbox' );
1484
				}
1485
1486
				/**
1487
				 * If the form has checkbox fields, enqueue dashicons
1488
				 * @see https://github.com/katzwebservices/GravityView/issues/536
1489
				 * @since 1.15
1490
				 */
1491
				if( gravityview_view_has_single_checkbox_or_radio( $data['form'], $data['fields'] ) ) {
1492
					$css_dependencies[] = 'dashicons';
1493
				}
1494
1495
				wp_register_script( 'gravityview-jquery-cookie', plugins_url( 'assets/lib/jquery.cookie/jquery.cookie.min.js', GRAVITYVIEW_FILE ), array( 'jquery' ), GravityView_Plugin::version, true );
1496
1497
				$script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
1498
1499
				wp_register_script( 'gravityview-fe-view', plugins_url( 'assets/js/fe-views' . $script_debug . '.js', GRAVITYVIEW_FILE ), apply_filters( 'gravityview_js_dependencies', $js_dependencies ) , GravityView_Plugin::version, true );
1500
1501
				wp_enqueue_script( 'gravityview-fe-view' );
1502
1503
				if ( ! empty( $data['atts']['sort_columns'] ) ) {
1504
					wp_enqueue_style( 'gravityview_font', plugins_url( 'assets/css/font.css', GRAVITYVIEW_FILE ), $css_dependencies, GravityView_Plugin::version, 'all' );
1505
				}
1506
1507
				$this->enqueue_default_style( $css_dependencies );
1508
1509
				self::add_style( $data['template_id'] );
1510
			}
1511
1512
			if ( 'wp_print_footer_scripts' === current_filter() ) {
1513
1514
				$js_localization = array(
1515
					'cookiepath' => COOKIEPATH,
1516
					'clear' => _x( 'Clear', 'Clear all data from the form', 'gravityview' ),
1517
					'reset' => _x( 'Reset', 'Reset the search form to the state that existed on page load', 'gravityview' ),
1518
				);
1519
1520
				/**
1521
				 * @filter `gravityview_js_localization` Modify the array passed to wp_localize_script()
1522
				 * @param array $js_localization The data padded to the Javascript file
1523
				 * @param array $views Array of View data arrays with View settings
1524
				 */
1525
				$js_localization = apply_filters( 'gravityview_js_localization', $js_localization, $views );
1526
1527
				wp_localize_script( 'gravityview-fe-view', 'gvGlobals', $js_localization );
1528
			}
1529
		}
1530
	}
1531
1532
	/**
1533
	 * Handle enqueuing the `gravityview_default_style` stylesheet
1534
	 *
1535
	 * @since 1.17
1536
	 *
1537
	 * @param array $css_dependencies Dependencies for the `gravityview_default_style` stylesheet
1538
	 *
1539
	 * @return void
1540
	 */
1541
	private function enqueue_default_style( $css_dependencies = array() ) {
1542
1543
		/**
1544
		 * @filter `gravityview_use_legacy_search_css` Should GravityView use the legacy Search Bar stylesheet (from before Version 1.17)?
1545
		 * @since 1.17
1546
		 * @param bool $use_legacy_search_style If true, loads `gv-legacy-search(-rtl).css`. If false, loads `gv-default-styles(-rtl).css`. `-rtl` is added on RTL websites. Default: `false`
1547
		 */
1548
		$use_legacy_search_style = apply_filters( 'gravityview_use_legacy_search_style', false );
1549
1550
		$rtl = is_rtl() ? '-rtl' : '';
1551
1552
		$css_file_base = $use_legacy_search_style ? 'gv-legacy-search' : 'gv-default-styles';
1553
1554
		$path = gravityview_css_url( $css_file_base . $rtl . '.css' );
1555
1556
		wp_enqueue_style( 'gravityview_default_style', $path, $css_dependencies, GravityView_Plugin::version, 'all' );
1557
	}
1558
1559
	/**
1560
	 * Add template extra style if exists
1561
	 * @param string $template_id
1562
	 */
1563
	public static function add_style( $template_id ) {
1564
1565
		if ( ! empty( $template_id ) && wp_style_is( 'gravityview_style_' . $template_id, 'registered' ) ) {
1566
			do_action( 'gravityview_log_debug', sprintf( '[add_style] Adding extra template style for %s', $template_id ) );
1567
			wp_enqueue_style( 'gravityview_style_' . $template_id );
1568
		} elseif ( empty( $template_id ) ) {
1569
			do_action( 'gravityview_log_error', '[add_style] Cannot add template style; template_id is empty' );
1570
		} else {
1571
			do_action( 'gravityview_log_error', sprintf( '[add_style] Cannot add template style; %s is not registered', 'gravityview_style_'.$template_id ) );
1572
		}
1573
1574
	}
1575
1576
1577
	/**
1578
	 * Inject the sorting links on the table columns
1579
	 *
1580
	 * Callback function for hook 'gravityview/template/field_label'
1581
	 * @see GravityView_API::field_label() (in includes/class-api.php)
1582
	 *
1583
	 * @since 1.7
1584
	 *
1585
	 * @param string $label Field label
1586
	 * @param array $field Field settings
1587
	 *
1588
	 * @return string Field Label
1589
	 */
1590
	public function add_columns_sort_links( $label = '', $field, $form ) {
1591
1592
		/**
1593
		 * Not a table-based template; don't add sort icons
1594
		 * @since 1.12
1595
		 */
1596
		if( ! preg_match( '/table/ism', GravityView_View::getInstance()->getTemplatePartSlug() ) ) {
1597
			return $label;
1598
		}
1599
1600
		if ( ! $this->is_field_sortable( $field['id'], $form ) ) {
1601
			return $label;
1602
		}
1603
1604
		$sorting = GravityView_View::getInstance()->getSorting();
1605
1606
		$class = 'gv-sort';
1607
1608
		$sort_field_id = self::_override_sorting_id_by_field_type( $field['id'], $form['id'] );
1609
1610
		$sort_args = array(
1611
			'sort' => $field['id'],
1612
			'dir' => 'asc',
1613
		);
1614
1615
		if ( ! empty( $sorting['key'] ) && (string) $sort_field_id === (string) $sorting['key'] ) {
1616
			//toggle sorting direction.
1617
			if ( 'asc' === $sorting['direction'] ) {
1618
				$sort_args['dir'] = 'desc';
1619
				$class .= ' gv-icon-sort-desc';
1620
			} else {
1621
				$sort_args['dir'] = 'asc';
1622
				$class .= ' gv-icon-sort-asc';
1623
			}
1624
		} else {
1625
			$class .= ' gv-icon-caret-up-down';
1626
		}
1627
1628
		$url = add_query_arg( $sort_args, remove_query_arg( array('pagenum') ) );
0 ignored issues
show
introduced by
No space after opening parenthesis of array is bad style
Loading history...
introduced by
No space before closing parenthesis of array is bad style
Loading history...
1629
1630
		return '<a href="'. esc_url_raw( $url ) .'" class="'. $class .'" ></a>&nbsp;'. $label;
1631
1632
	}
1633
1634
	/**
1635
	 * Checks if field (column) is sortable
1636
	 *
1637
	 * @param string $field Field settings
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...
1638
	 * @param array $form Gravity Forms form array
1639
	 *
1640
	 * @since 1.7
1641
	 *
1642
	 * @return bool True: Yes, field is sortable; False: not sortable
1643
	 */
1644
	public function is_field_sortable( $field_id = '', $form = array() ) {
1645
1646
		$field_type = $field_id;
1647
1648
		if( is_numeric( $field_id ) ) {
1649
			$field = GFFormsModel::get_field( $form, $field_id );
1650
			$field_type = $field->type;
1651
		}
1652
1653
		$not_sortable = array(
1654
			'edit_link',
1655
			'delete_link',
1656
		);
1657
1658
		/**
1659
		 * @filter `gravityview/sortable/field_blacklist` Modify what fields should never be sortable.
1660
		 * @since 1.7
1661
		 * @param[in,out] array $not_sortable Array of field types that aren't sortable
1662
		 * @param string $field_type Field type to check whether the field is sortable
1663
		 * @param array $form Gravity Forms form
1664
		 */
1665
		$not_sortable = apply_filters( 'gravityview/sortable/field_blacklist', $not_sortable, $field_type, $form );
1666
1667
		if ( in_array( $field_type, $not_sortable ) ) {
1668
			return false;
1669
		}
1670
1671
		return apply_filters( "gravityview/sortable/formfield_{$form['id']}_{$field_id}", apply_filters( "gravityview/sortable/field_{$field_id}", true, $form ) );
1672
1673
	}
1674
1675
}
1676
1677
GravityView_frontend::getInstance();
1678
1679
1680
1681