Completed
Push — feature/codesniffer-fixes ( c7a4f1...41059d )
by Scott Kingsley
13:22
created

general.php ➔ pods_version_check()   C

Complexity

Conditions 7
Paths 9

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 9
nop 4
dl 0
loc 22
rs 6.9811
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 18 and the first side effect is on line 101.

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
 * @package Pods\Global\Functions\General
4
 */
5
/**
6
 * Standardize queries and error reporting. It replaces @wp_ with $wpdb->prefix.
7
 *
8
 * @see   PodsData::query
9
 *
10
 * @param string $sql              SQL Query
11
 * @param string $error            (optional) The failure message
12
 * @param string $results_error    (optional) Throw an error if a records are found
0 ignored issues
show
Documentation introduced by
Should the type for parameter $results_error not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
13
 * @param string $no_results_error (optional) Throw an error if no records are found
0 ignored issues
show
Documentation introduced by
Should the type for parameter $no_results_error not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
14
 *
15
 * @return array|bool|mixed|null|void
16
 * @since 2.0
17
 */
18
function pods_query( $sql, $error = 'Database Error', $results_error = null, $no_results_error = null ) {
19
20
	$podsdata = pods_data();
21
22
	$sql = apply_filters( 'pods_query_sql', $sql, $error, $results_error, $no_results_error );
23
	$sql = $podsdata->get_sql( $sql );
24
25
	if ( is_array( $error ) ) {
26
		if ( ! is_array( $sql ) ) {
27
			$sql = array( $sql, $error );
28
		}
29
30
		$error = 'Database Error';
31
	}
32
33
	if ( 1 === (int) pods_v( 'pods_debug_sql_all' ) && is_user_logged_in() && pods_is_admin( array( 'pods' ) ) ) {
34
		$debug_sql = $sql;
35
36
		echo '<textarea cols="100" rows="24">';
37
38
		if ( is_array( $debug_sql ) ) {
39
			$debug_sql = print_r( $debug_sql, true );
40
		}
41
42
		echo esc_textarea( $debug_sql );
43
44
		echo '</textarea>';
45
	}
46
47
	return $podsdata->query( $sql, $error, $results_error, $no_results_error );
48
}
49
50
/**
51
 * Standardize filters / actions
52
 *
53
 * @param string $scope Scope of the filter / action (ui for PodsUI, api for PodsAPI, etc..)
54
 * @param string $name  Name of filter / action to run
55
 * @param mixed  $args  (optional) Arguments to send to filter / action
56
 * @param object $obj   (optional) Object to reference for filter / action
0 ignored issues
show
Documentation introduced by
Should the type for parameter $obj not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
57
 *
58
 * @return mixed
59
 * @since 2.0
60
 * @todo  Need to figure out how to handle $scope = 'pods' for the Pods class
61
 */
62
function pods_do_hook( $scope, $name, $args = null, $obj = null ) {
63
64
	// Add filter name
65
	array_unshift( $args, "pods_{$scope}_{$name}" );
66
67
	// Add object
68
	$args[] = $obj;
69
70
	// Run apply_filters and give it all the arguments
71
	$args = call_user_func_array( 'apply_filters', $args );
72
73
	return $args;
74
}
75
76
/**
77
 * Message / Notice handling for Admin UI
78
 *
79
 * @param string $message The notice / error message shown
80
 * @param string $type    Message type
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
81
 *
82
 * @return void
83
 */
84
function pods_message( $message, $type = null ) {
85
86
	if ( empty( $type ) || ! in_array( $type, array( 'notice', 'error' ), true ) ) {
87
		$type = 'notice';
88
	}
89
90
	$class = '';
91
92
	if ( 'notice' === $type ) {
93
		$class = 'updated';
94
	} elseif ( 'error' === $type ) {
95
		$class = 'error';
96
	}
97
98
	echo '<div id="message" class="' . esc_attr( $class ) . ' fade"><p>' . $message . '</p></div>';
99
}
100
101
$GLOBALS['pods_errors'] = array();
102
103
/**
104
 * Error Handling which throws / displays errors
105
 *
106
 * @param string|array        $error The error message(s) to be thrown / displayed.
107
 * @param object|boolean|null $obj   If $obj->display_errors is set and is set to true it will display errors, if
108
 *                                   boolean and is set to true it will display errors.
109
 *
110
 * @throws Exception Throws exception for developer-oriented error handling.
111
 *
112
 * @return mixed
113
 *
114
 * @since 2.0
115
 */
116
function pods_error( $error, $obj = null ) {
117
118
	global $pods_errors;
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...
119
120
	$error_mode = 'exception';
121
122
	if ( is_object( $obj ) && isset( $obj->display_errors ) ) {
123
		if ( true === $obj->display_errors ) {
124
			$error_mode = 'exit';
125
		} elseif ( false === $obj->display_errors ) {
126
			$error_mode = 'exception';
127
		} else {
128
			$error_mode = $obj->display_errors;
129
		}
130
	} elseif ( true === $obj ) {
131
		$error_mode = 'exit';
132
	} elseif ( false === $obj ) {
133
		$error_mode = 'exception';
134
	} elseif ( is_string( $obj ) ) {
135
		$error_mode = $obj;
136
	}
137
138
	if ( is_object( $error ) && 'Exception' === get_class( $error ) ) {
139
		$error = $error->getMessage();
140
141
		$error_mode = 'exception';
142
	}
143
144
	/**
145
	 * @var string $error_mode Throw an exception, exit with the message, return false, or return WP_Error
146
	 */
147
	if ( ! in_array( $error_mode, array( 'exception', 'exit', 'false', 'wp_error' ), true ) ) {
148
		$error_mode = 'exception';
149
	}
150
151
	/**
152
	 * Filter the error mode used by pods_error.
153
	 *
154
	 * @param string                     $error_mode Error mode
155
	 * @param string|array               $error      Error message(s)
156
	 * @param object|boolean|string|null $obj
157
	 */
158
	$error_mode = apply_filters( 'pods_error_mode', $error_mode, $error, $obj );
159
160
	if ( is_array( $error ) ) {
161
		$error = array_map( 'wp_kses_post', $error );
162
163
		if ( 1 === count( $error ) ) {
164
			$error = current( $error );
165
166
			// Create WP_Error for use later.
167
			$wp_error = new WP_Error( 'pods-error-' . md5( $error ), $error );
168
		} else {
169
			// Create WP_Error for use later.
170
			$wp_error = new WP_Error();
171
172
			foreach ( $error as $error_message ) {
173
				$wp_error->add( 'pods-error-' . md5( $error_message ), $error_message );
174
			}
175
176
			if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
177
				$error = __( 'The following issue occurred:', 'pods' ) . "\n\n- " . implode( "\n- ", $error );
178
			} else {
179
				$error = __( 'The following issues occurred:', 'pods' ) . "\n<ul><li>" . implode( "</li>\n<li>", $error ) . '</li></ul>';
180
			}
181
		}
182
	} else {
183
		if ( is_object( $error ) ) {
184
			$error = __( 'An unknown error has occurred', 'pods' );
185
		}
186
187
		$error = wp_kses_post( $error );
188
189
		// Create WP_Error for use later.
190
		$wp_error = new WP_Error( 'pods-error-' . md5( $error ), $error );
191
	}//end if
192
193
	$last_error = $pods_errors;
194
195
	$pods_errors = array();
196
197
	if ( $last_error === $error && 'exception' === $error_mode ) {
198
		$error_mode = 'exit';
199
	}
200
201
	if ( ! empty( $error ) ) {
202
		if ( 'exception' === $error_mode ) {
203
			$exception_bypass = apply_filters( 'pods_error_exception', null, $error );
204
205
			if ( null !== $exception_bypass ) {
206
				return $exception_bypass;
207
			}
208
209
			$pods_errors = $error;
210
211
			set_exception_handler( 'pods_error' );
212
213
			throw new Exception( $error );
214
		} elseif ( 'exit' === $error_mode ) {
215
			$die_bypass = apply_filters( 'pods_error_die', null, $error );
216
217
			if ( null !== $die_bypass ) {
218
				return $die_bypass;
219
			}
220
221
			// die with error
222
			if ( ! defined( 'DOING_AJAX' ) && ! headers_sent() && ( is_admin() || false !== strpos( $_SERVER['REQUEST_URI'], 'wp-comments-post.php' ) ) ) {
223
				wp_die( $error, '', array( 'back_link' => true ) );
224
			} else {
225
				die( sprintf( '<e>%s</e>', $error ) );
226
			}
227
		} elseif ( 'wp_error' === $error_mode ) {
228
			return $wp_error;
229
		}//end if
230
	}//end if
231
232
	return false;
233
234
}
235
236
/**
237
 * Debug variable used in pods_debug to count the instances debug is used
238
 */
239
global $pods_debug;
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...
240
$pods_debug = 0;
241
/**
242
 * Debugging common issues using this function saves a few lines and is compatible with
243
 *
244
 * @param mixed   $debug The error message to be thrown / displayed
245
 * @param boolean $die   If set to true, a die() will occur, if set to (int) 2 then a wp_die() will occur
246
 * @param string  $prefix
247
 *
248
 * @return void
249
 *
250
 * @since 2.0
251
 */
252
function pods_debug( $debug = '_null', $die = false, $prefix = '_null' ) {
253
254
	global $pods_debug;
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...
255
256
	$pods_debug ++;
257
258
	ob_start();
259
260
	if ( '_null' !== $prefix ) {
261
		var_dump( $prefix );
0 ignored issues
show
Security Debugging Code introduced by
var_dump($prefix); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
262
	}
263
264
	if ( '_null' !== $debug ) {
265
		var_dump( $debug );
266
	} else {
267
		var_dump( 'Pods Debug #' . $pods_debug );
268
	}
269
270
	$debug = ob_get_clean();
271
272
	if ( false === strpos( $debug, "<pre class='xdebug-var-dump'" ) && ( ! ini_get( 'xdebug.overload_var_dump' ) && ! ini_get( 'html_errors' ) ) ) {
273
		if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
274
			$debug = esc_html( $debug );
275
		}
276
277
		$debug = '<pre>' . $debug . '</pre>';
278
	}
279
280
	$debug = '<e>' . $debug;
281
282
	if ( 2 === $die ) {
283
		wp_die( $debug, '', array( 'back_link' => true ) );
284
	} elseif ( true === $die ) {
285
		die( $debug );
286
	}
287
288
	echo $debug;
289
}
290
291
/**
292
 * Determine if user has admin access
293
 *
294
 * @param string|array $cap Additional capabilities to check
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cap not be string|array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
295
 *
296
 * @return bool Whether user has admin access
297
 *
298
 * @since 2.3.5
299
 */
300
function pods_is_admin( $cap = null ) {
301
302
	if ( is_user_logged_in() ) {
303
		// Default is_super_admin() checks against this.
304
		$pods_admin_capabilities = array(
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $pods_admin_capabilities exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
305
			'delete_users',
306
		);
307
308
		$pods_admin_capabilities = apply_filters( 'pods_admin_capabilities', $pods_admin_capabilities, $cap );
309
310
		if ( is_multisite() && is_super_admin() ) {
311
			return apply_filters( 'pods_is_admin', true, $cap, '_super_admin' );
312
		}
313
314
		if ( empty( $cap ) ) {
315
			$cap = array();
316
		} else {
317
			$cap = (array) $cap;
318
		}
319
320
		$cap = array_unique( array_filter( array_merge( $pods_admin_capabilities, $cap ) ) );
321
322
		foreach ( $cap as $capability ) {
323
			if ( current_user_can( $capability ) ) {
324
				return apply_filters( 'pods_is_admin', true, $cap, $capability );
325
			}
326
		}
327
	}//end if
328
329
	return apply_filters( 'pods_is_admin', false, $cap, null );
330
}
331
332
/**
333
 * Determine if Developer Mode is enabled
334
 *
335
 * @return bool Whether Developer Mode is enabled
336
 *
337
 * @since 2.3
338
 */
339
function pods_developer() {
340
341
	if ( defined( 'PODS_DEVELOPER' ) && PODS_DEVELOPER ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return (bool) (defined('...R') && PODS_DEVELOPER);.
Loading history...
342
		return true;
343
	}
344
345
	return false;
346
}
347
348
/**
349
 * Determine if Tableless Mode is enabled
350
 *
351
 * @return bool Whether Tableless Mode is enabled
352
 *
353
 * @since 2.3
354
 */
355
function pods_tableless() {
356
357
	if ( defined( 'PODS_TABLELESS' ) && PODS_TABLELESS ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return defined('PODS_TAB...SS') && PODS_TABLELESS;.
Loading history...
358
		return true;
359
	}
360
361
	return false;
362
}
363
364
/**
365
 * Determine if Strict Mode is enabled
366
 *
367
 * @param bool $include_debug Whether to include WP_DEBUG in strictness level
368
 *
369
 * @return bool Whether Strict Mode is enabled
370
 *
371
 * @since 2.3.5
372
 */
373
function pods_strict( $include_debug = true ) {
374
375
	if ( defined( 'PODS_STRICT' ) && PODS_STRICT ) {
376
		// Deprecated PODS_STRICT_MODE since 2.3.5
377
		return true;
378
	} elseif ( defined( 'PODS_STRICT_MODE' ) && PODS_STRICT_MODE && pods_allow_deprecated( false ) ) {
379
		return true;
380
	} elseif ( $include_debug && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
381
		return true;
382
	}
383
384
	return false;
385
386
}
387
388
/**
389
 * Determine if Deprecated Mode is enabled
390
 *
391
 * @param bool $include_debug Whether to include strict mode
0 ignored issues
show
Bug introduced by
There is no parameter named $include_debug. 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...
392
 *
393
 * @return bool Whether Deprecated Mode is enabled
394
 *
395
 * @since 2.3.10
396
 */
397
function pods_allow_deprecated( $strict = true ) {
398
399
	if ( $strict && pods_strict() ) {
400
		return false;
401
	} elseif ( ! defined( 'PODS_DEPRECATED' ) || PODS_DEPRECATED ) {
402
		return true;
403
	}
404
405
	return false;
406
407
}
408
409
/**
410
 * Determine if Pods API Caching is enabled
411
 *
412
 * @return bool Whether Pods API Caching is enabled
413
 *
414
 * @since 2.3.9
415
 */
416
function pods_api_cache() {
417
418
	if ( defined( 'PODS_API_CACHE' ) && ! PODS_API_CACHE ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !(defined('PODS_A...') && !PODS_API_CACHE);.
Loading history...
419
		return false;
420
	}
421
422
	return true;
423
}
424
425
/**
426
 * Marks a function as deprecated and informs when it has been used.
427
 *
428
 * There is a hook deprecated_function_run that will be called that can be used
429
 * to get the backtrace up to what file and function called the deprecated
430
 * function.
431
 *
432
 * The current behavior is to trigger a user error if WP_DEBUG is true.
433
 *
434
 * This function is to be used in every function that is deprecated.
435
 *
436
 * @uses  do_action() Calls 'deprecated_function_run' and passes the function name, what to use instead,
437
 *   and the version the function was deprecated in.
438
 * @uses  apply_filters() Calls 'deprecated_function_trigger_error' and expects boolean value of true to do
439
 *   trigger or false to not trigger error.
440
 *
441
 * @param string $function    The function that was called
442
 * @param string $version     The version of WordPress that deprecated the function
443
 * @param string $replacement Optional. The function that should have been called
0 ignored issues
show
Documentation introduced by
Should the type for parameter $replacement not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
444
 *
445
 * @since 2.0
446
 */
447
function pods_deprecated( $function, $version, $replacement = null ) {
448
449
	if ( ! version_compare( $version, PODS_VERSION, '<=' ) && ! version_compare( $version . '-a-0', PODS_VERSION, '<=' ) ) {
450
		return;
451
	}
452
453
	do_action( 'deprecated_function_run', $function, $replacement, $version );
454
455
	// Allow plugin to filter the output error trigger
456
	if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
457
		if ( ! is_null( $replacement ) ) {
458
			$error = __( '%1$s has been <strong>deprecated</strong> since Pods version %2$s! Use %3$s instead.', 'pods' );
459
		} else {
460
			$error = __( '%1$s has been <strong>deprecated</strong> since Pods version %2$s with no alternative available.', 'pods' );
461
		}
462
463
		trigger_error( sprintf( $error, $function, $version, $replacement ) );
464
	}
465
}
466
467
/**
468
 * Inline help
469
 *
470
 * @param string $text Help text
471
 * @param string $url  Documentation URL
0 ignored issues
show
Documentation introduced by
Should the type for parameter $url not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
472
 *
473
 * @return void
474
 *
475
 * @since 2.0
476
 */
477
function pods_help( $text, $url = null ) {
478
479
	if ( ! wp_script_is( 'jquery-qtip2', 'registered' ) ) {
480
		wp_register_script( 'jquery-qtip2', PODS_URL . 'ui/js/jquery.qtip.min.js', array( 'jquery' ), '2.2' );
481
	} elseif ( ! wp_script_is( 'jquery-qtip2', 'queue' ) && ! wp_script_is( 'jquery-qtip2', 'to_do' ) && ! wp_script_is( 'jquery-qtip2', 'done' ) ) {
482
		wp_enqueue_script( 'jquery-qtip2' );
483
	}
484
485
	if ( ! wp_script_is( 'pods-qtip-init', 'registered' ) ) {
486
		wp_register_script(
487
			'pods-qtip-init', PODS_URL . 'ui/js/qtip.js', array(
488
				'jquery',
489
				'jquery-qtip2',
490
			), PODS_VERSION
491
		);
492
	} elseif ( ! wp_script_is( 'pods-qtip-init', 'queue' ) && ! wp_script_is( 'pods-qtip-init', 'to_do' ) && ! wp_script_is( 'pods-qtip-init', 'done' ) ) {
493
		wp_enqueue_script( 'pods-qtip-init' );
494
	}
495
496
	if ( is_array( $text ) ) {
497
		if ( isset( $text[1] ) ) {
498
			$url = $text[1];
499
		}
500
501
		$text = $text[0];
502
	}
503
504
	if ( 'help' === $text ) {
505
		return;
506
	}
507
508
	if ( 0 < strlen( $url ) ) {
509
		$text .= '<br /><br /><a href="' . $url . '" target="_blank">' . __( 'Find out more', 'pods' ) . ' &raquo;</a>';
510
	}
511
512
	echo '<img src="' . esc_url( PODS_URL ) . 'ui/images/help.png" alt="' . esc_attr( $text ) . '" class="pods-icon pods-qtip" />';
513
}
514
515
/**
516
 * Check whether or not something is a specific version minimum and/or maximum
517
 *
518
 * @param string $minimum_version Minimum version
519
 * @param string $comparison      Comparison operator
520
 * @param string $maximum_version Maximum version
0 ignored issues
show
Documentation introduced by
Should the type for parameter $maximum_version not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
521
 *
522
 * @return bool
523
 */
524
function pods_version_check( $what, $minimum_version, $comparison = '<=', $maximum_version = null ) {
525
526
	global $wp_version, $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

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

1. Pass all data via parameters

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

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

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

    public function myFunction() {
        // Do something
    }
}
Loading history...
527
528
	if ( 'php' === $what ) {
529
		$version = phpversion();
530
	} elseif ( 'mysql' === $what ) {
531
		$version = $wpdb->db_version();
532
	} else {
533
		$version = $wp_version;
534
	}
535
536
	if ( ! empty( $minimum_version ) && ! version_compare( $minimum_version, $version, $comparison ) ) {
537
		return false;
538
	}
539
540
	if ( ! empty( $maximum_version ) && ! version_compare( $version, $maximum_version, $comparison ) ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !(!empty($maximum...version, $comparison));.
Loading history...
541
		return false;
542
	}
543
544
	return true;
545
}
546
547
/**
548
 * Run a Pods Helper
549
 *
550
 * @param string $helper_name Helper Name
551
 * @param string $value       Value to run Helper on
0 ignored issues
show
Documentation introduced by
Should the type for parameter $value not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
552
 * @param string $name        Field name.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
553
 *
554
 * @return bool
555
 * @since 1.7.5
556
 */
557
function pods_helper( $helper_name, $value = null, $name = null ) {
558
559
	return pods()->helper( $helper_name, $value, $name );
560
}
561
562
/**
563
 * Get the full URL of the current page
564
 *
565
 * @return string Full URL of the current page
566
 * @since 2.3
567
 */
568
function pods_current_url() {
569
570
	$url = 'http';
571
572
	if ( isset( $_SERVER['HTTPS'] ) && 'off' !== $_SERVER['HTTPS'] && 0 !== $_SERVER['HTTPS'] ) {
573
		$url = 'https';
574
	}
575
576
	$url .= '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
577
578
	return apply_filters( 'pods_current_url', $url );
579
}
580
581
/**
582
 * Find out if the current page has a valid $pods
583
 *
584
 * @param object $object The Pod Object currently checking (optional)
0 ignored issues
show
Documentation introduced by
Should the type for parameter $object not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
585
 *
586
 * @return bool
587
 * @since 2.0
588
 */
589
function is_pod( $object = null ) {
590
591
	global $pods, $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...
592
593
	if ( is_object( $object ) && isset( $object->pod ) && ! empty( $object->pod ) ) {
594
		return true;
595
	} elseif ( is_object( $pods ) && isset( $pods->pod ) && ! empty( $pods->pod ) ) {
596
		return true;
597
	} elseif ( is_object( $post ) && isset( $post->post_type ) && pods_api()->pod_exists( $post->post_type, 'post_type' ) ) {
598
		return true;
599
	}
600
601
	return false;
602
}
603
604
/**
605
 * See if the current user has a certain privilege
606
 *
607
 * @param mixed  $privs  The privilege name or names (array if multiple)
608
 * @param string $method The access method ("AND", "OR")
609
 *
610
 * @return bool
611
 * @since 1.2.0
612
 */
613
function pods_access( $privs, $method = 'OR' ) {
614
615
	// Convert $privs to an array
616
	$privs = (array) $privs;
617
618
	// Convert $method to uppercase
619
	$method = strtoupper( $method );
620
621
	$check = apply_filters( 'pods_access', null, $privs, $method );
622
	if ( null !== $check && is_bool( $check ) ) {
623
		return $check;
624
	}
625
626
	if ( ! is_user_logged_in() ) {
627
		return false;
628
	}
629
630
	if ( pods_is_admin( array( 'pods', 'pods_content' ) ) ) {
631
		return true;
632
	}
633
634
	// Store approved privs when using "AND"
635
	$approved_privs = array();
636
637
	// Loop through the user's roles
638
	foreach ( $privs as $priv ) {
639
		if ( 0 === strpos( $priv, 'pod_' ) ) {
640
			$priv = pods_str_replace( 'pod_', 'pods_edit_', $priv, 1 );
641
		}
642
643
		if ( 0 === strpos( $priv, 'manage_' ) ) {
644
			$priv = pods_str_replace( 'manage_', 'pods_', $priv, 1 );
645
		}
646
647
		if ( current_user_can( $priv ) ) {
648
			if ( 'OR' === $method ) {
649
				return true;
650
			}
651
652
			$approved_privs[ $priv ] = true;
653
		}
654
	}
655
	if ( 'AND' === strtoupper( $method ) ) {
656
		foreach ( $privs as $priv ) {
657
			if ( 0 === strpos( $priv, 'pod_' ) ) {
658
				$priv = pods_str_replace( 'pod_', 'pods_edit_', $priv, 1 );
659
			}
660
661
			if ( 0 === strpos( $priv, 'manage_' ) ) {
662
				$priv = pods_str_replace( 'manage_', 'pods_', $priv, 1 );
663
			}
664
665
			if ( ! isset( $approved_privs[ $priv ] ) ) {
666
				return false;
667
			}
668
		}
669
670
		return true;
671
	}
672
673
	return false;
674
}
675
676
/**
677
 * Shortcode support for use anywhere that support WP Shortcodes
678
 *
679
 * @param array  $tags    An associative array of shortcode properties
680
 * @param string $content A string that represents a template override
0 ignored issues
show
Documentation introduced by
Should the type for parameter $content not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
681
 *
682
 * @return string
683
 * @since 1.6.7
684
 */
685
function pods_shortcode( $tags, $content = null ) {
686
687
	if ( defined( 'PODS_DISABLE_SHORTCODE' ) && PODS_DISABLE_SHORTCODE ) {
688
		return '';
689
	}
690
691
	// For enforcing pagination parameters when not displaying pagination
692
	$page   = 1;
693
	$offset = 0;
694
695
	if ( isset( $tags['page'] ) ) {
696
		$page = (int) $tags['page'];
697
		$page = max( $page, 1 );
698
	}
699
700
	if ( isset( $tags['offset'] ) ) {
701
		$offset = (int) $tags['offset'];
702
		$offset = max( $offset, 0 );
703
	}
704
705
	$defaults = array(
706
		'use_current'         => false,
707
		'name'                => null,
708
		'id'                  => null,
709
		'slug'                => null,
710
		'select'              => null,
711
		'join'                => null,
712
		'order'               => null,
713
		'orderby'             => null,
714
		'limit'               => null,
715
		'where'               => null,
716
		'having'              => null,
717
		'groupby'             => null,
718
		'search'              => true,
719
		'pagination'          => false,
720
		'page'                => null,
721
		'offset'              => null,
722
		'filters'             => false,
723
		'filters_label'       => null,
724
		'filters_location'    => 'before',
725
		'pagination_label'    => null,
726
		'pagination_location' => 'after',
727
		'field'               => null,
728
		'col'                 => null,
729
		'template'            => null,
730
		'pods_page'           => null,
731
		'helper'              => null,
732
		'form'                => null,
733
		'fields'              => null,
734
		'label'               => null,
735
		'thank_you'           => null,
736
		'view'                => null,
737
		'cache_mode'          => 'none',
738
		'expires'             => 0,
739
		'shortcodes'          => false,
740
	);
741
742
	if ( ! empty( $tags ) ) {
743
		$tags = array_merge( $defaults, $tags );
744
	} else {
745
		$tags = $defaults;
746
	}
747
748
	$tags = apply_filters( 'pods_shortcode', $tags );
749
750
	$tags['pagination']  = filter_var( $tags['pagination'], FILTER_VALIDATE_BOOLEAN );
751
	$tags['search']      = filter_var( $tags['pagination'], FILTER_VALIDATE_BOOLEAN );
752
	$tags['use_current'] = filter_var( $tags['use_current'], FILTER_VALIDATE_BOOLEAN );
753
754
	if ( empty( $content ) ) {
755
		$content = null;
756
	}
757
758
	// Allow views only if not targeting a file path (must be within theme)
759
	if ( 0 < strlen( $tags['view'] ) ) {
760
		$return = '';
761
762
		if ( ! file_exists( $tags['view'] ) ) {
763
			$return = pods_view( $tags['view'], null, (int) $tags['expires'], $tags['cache_mode'], true );
764
765
			if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
766
				$return = do_shortcode( $return );
767
			}
768
		}
769
770
		return $return;
771
	}
772
773
	if ( ! $tags['use_current'] && empty( $tags['name'] ) ) {
774
		if ( in_the_loop() || is_singular() ) {
775
			$pod = pods( get_post_type(), get_the_ID(), false );
776
777
			if ( ! empty( $pod ) ) {
778
				$tags['name'] = get_post_type();
779
				$id           = $tags['id'] = get_the_ID();
780
			}
781
		}
782
783
		if ( empty( $tags['name'] ) ) {
784
			return '<p>Please provide a Pod name</p>';
785
		}
786
	}
787
788
	if ( ! empty( $tags['col'] ) ) {
789
		$tags['field'] = $tags['col'];
790
791
		unset( $tags['col'] );
792
	}
793
794
	if ( ! empty( $tags['order'] ) ) {
795
		$tags['orderby'] = $tags['order'];
796
797
		unset( $tags['order'] );
798
	}
799
800
	if ( empty( $content ) && empty( $tags['pods_page'] ) && empty( $tags['template'] ) && empty( $tags['field'] ) && empty( $tags['form'] ) ) {
801
		return '<p>Please provide either a template or field name</p>';
802
	}
803
804
	if ( ! $tags['use_current'] && ! isset( $id ) ) {
805
		// id > slug (if both exist)
806
		$id = null;
807
808
		if ( ! empty( $tags['slug'] ) ) {
809
			$id = $tags['slug'];
810
811
			if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
812
				$id = pods_evaluate_tags( $id );
813
			}
814
		}
815
816
		if ( ! empty( $tags['id'] ) ) {
817
			$id = $tags['id'];
818
819
			if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
820
				$id = pods_evaluate_tags( $id );
821
			}
822
823
			if ( is_numeric( $id ) ) {
824
				$id = absint( $id );
825
			}
826
		}
827
	}//end if
828
829
	if ( ! isset( $pod ) ) {
830
		if ( ! $tags['use_current'] ) {
831
			$pod = pods( $tags['name'], $id );
0 ignored issues
show
Bug introduced by
The variable $id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
832
		} else {
833
			$pod = pods();
834
			$id  = $pod->id();
835
		}
836
	}
837
838
	if ( empty( $pod ) || ! $pod->valid() ) {
839
		return '<p>Pod not found</p>';
840
	}
841
842
	$found = 0;
843
844
	$is_singular = ( ! empty( $id ) || $tags['use_current'] );
845
846
	if ( ! $is_singular ) {
847
		$params = array();
848
849
		if ( ! defined( 'PODS_DISABLE_SHORTCODE_SQL' ) || ! PODS_DISABLE_SHORTCODE_SQL ) {
850
			if ( 0 < strlen( $tags['orderby'] ) ) {
851
				$params['orderby'] = $tags['orderby'];
852
			}
853
854
			if ( 0 < strlen( $tags['where'] ) ) {
855
				$params['where'] = $tags['where'];
856
857
				if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
858
					$params['where'] = pods_evaluate_tags( html_entity_decode( $params['where'] ) );
859
				}
860
			}
861
862
			if ( 0 < strlen( $tags['having'] ) ) {
863
				$params['having'] = $tags['having'];
864
865
				if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
866
					$params['having'] = pods_evaluate_tags( html_entity_decode( $params['having'] ) );
867
				}
868
			}
869
870
			if ( 0 < strlen( $tags['groupby'] ) ) {
871
				$params['groupby'] = $tags['groupby'];
872
			}
873
874
			if ( 0 < strlen( $tags['select'] ) ) {
875
				$params['select'] = $tags['select'];
876
			}
877
			if ( 0 < strlen( $tags['join'] ) ) {
878
				$params['join'] = $tags['join'];
879
			}
880
		}//end if
881
882
		// Forms require params set
883
		if ( ! empty( $params ) || empty( $tags['form'] ) ) {
884
			if ( ! empty( $tags['limit'] ) ) {
885
				$params['limit'] = (int) $tags['limit'];
886
			}
887
888
			$params['search'] = $tags['search'];
889
890
			$params['pagination'] = $tags['pagination'];
891
892
			// If we aren't displaying pagination, we need to enforce page/offset
893
			if ( ! $params['pagination'] ) {
894
				$params['page']   = $page;
895
				$params['offset'] = $offset;
896
897
				// Force pagination on, we need it and we're enforcing page/offset
898
				$params['pagination'] = true;
899
			} else {
900
				// If we are displaying pagination, allow page/offset override only if *set*
901
				if ( isset( $tags['page'] ) ) {
902
					$params['page'] = (int) $tags['page'];
903
					$params['page'] = max( $params['page'], 1 );
904
				}
905
906
				if ( isset( $tags['offset'] ) ) {
907
					$params['offset'] = (int) $tags['offset'];
908
					$params['offset'] = max( $params['offset'], 0 );
909
				}
910
			}
911
912
			if ( ! empty( $tags['cache_mode'] ) && 'none' !== $tags['cache_mode'] ) {
913
				$params['cache_mode'] = $tags['cache_mode'];
914
				$params['expires']    = (int) $tags['expires'];
915
			}
916
917
			$params = apply_filters( 'pods_shortcode_findrecords_params', $params, $pod, $tags );
918
919
			$pod->find( $params );
920
921
			$found = $pod->total();
922
		}//end if
923
	}//end if
924
925
	if ( ! empty( $tags['form'] ) ) {
926
		if ( 'user' === $pod->pod ) {
927
			if ( false !== strpos( $tags['fields'], '_capabilities' ) || false !== strpos( $tags['fields'], '_user_level' ) ) {
928
				// Further hardening of User-based forms
929
				return '';
930
			} elseif ( $is_singular && ( ! defined( 'PODS_SHORTCODE_ALLOW_USER_EDIT' ) || ! PODS_SHORTCODE_ALLOW_USER_EDIT ) ) {
931
				// Only explicitly allow user edit forms
932
				return '';
933
			}
934
		}
935
936
		return $pod->form( $tags['fields'], $tags['label'], $tags['thank_you'] );
937
	} elseif ( ! empty( $tags['field'] ) ) {
938
		if ( empty( $tags['helper'] ) ) {
939
			$return = $pod->display( $tags['field'] );
940
		} else {
941
			$return = $pod->helper( $tags['helper'], $pod->field( $tags['field'] ), $tags['field'] );
942
		}
943
944
		if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
945
			$return = do_shortcode( $return );
946
		}
947
948
		return $return;
949
	} elseif ( ! empty( $tags['pods_page'] ) && class_exists( 'Pods_Pages' ) ) {
950
		$pods_page = Pods_Pages::exists( $tags['pods_page'] );
951
952
		if ( empty( $pods_page ) ) {
953
			return '<p>Pods Page not found</p>';
954
		}
955
956
		$return = Pods_Pages::content( true, $pods_page );
957
958
		if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
959
			$return = do_shortcode( $return );
960
		}
961
962
		return $return;
963
	}//end if
964
965
	ob_start();
966
967
	if ( ! $is_singular && false !== $tags['filters'] && 'before' === $tags['filters_location'] ) {
968
		echo $pod->filters( $tags['filters'], $tags['filters_label'] );
0 ignored issues
show
Unused Code introduced by
The call to Pods::filters() has too many arguments starting with $tags['filters_label'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
969
	}
970
971
	if ( ! $is_singular && 0 < $found && true === $tags['pagination'] && in_array(
972
		$tags['pagination_location'], array(
973
			'before',
974
			'both',
975
		), true
976
	) ) {
977
		echo $pod->pagination( $tags['pagination_label'] );
978
	}
979
980
	echo $pod->template( $tags['template'], $content );
981
982
	if ( ! $is_singular && 0 < $found && true === $tags['pagination'] && in_array(
983
		$tags['pagination_location'], array(
984
			'after',
985
			'both',
986
		), true
987
	) ) {
988
		echo $pod->pagination( $tags['pagination_label'] );
989
	}
990
991
	if ( ! $is_singular && false !== $tags['filters'] && 'after' === $tags['filters_location'] ) {
992
		echo $pod->filters( $tags['filters'], $tags['filters_label'] );
0 ignored issues
show
Unused Code introduced by
The call to Pods::filters() has too many arguments starting with $tags['filters_label'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
993
	}
994
995
	$return = ob_get_clean();
996
997
	if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
998
		$return = do_shortcode( $return );
999
	}
1000
1001
	return $return;
1002
}
1003
1004
/**
1005
 * Form Shortcode support for use anywhere that support WP Shortcodes
1006
 *
1007
 * @param array  $tags    An associative array of shortcode properties
1008
 * @param string $content Not currently used
0 ignored issues
show
Documentation introduced by
Should the type for parameter $content not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1009
 *
1010
 * @return string
1011
 * @since 2.3
1012
 */
1013
function pods_shortcode_form( $tags, $content = null ) {
1014
1015
	$tags['form'] = 1;
1016
1017
	return pods_shortcode( $tags );
1018
}
1019
1020
/**
1021
 * Fork of WordPress do_shortcode that allows specifying which shortcodes are ran.
1022
 *
1023
 * Search content for shortcodes and filter shortcodes through their hooks.
1024
 *
1025
 * If there are no shortcode tags defined, then the content will be returned
1026
 * without any filtering. This might cause issues when plugins are disabled but
1027
 * the shortcode will still show up in the post or content.
1028
 *
1029
 * @since 2.4.3
1030
 *
1031
 * @uses  $shortcode_tags
1032
 * @uses  get_shortcode_regex() Gets the search pattern for searching shortcodes.
1033
 *
1034
 * @param string $content    Content to search for shortcodes
1035
 * @param array  $shortcodes Array of shortcodes to run
1036
 *
1037
 * @return string Content with shortcodes filtered out.
1038
 */
1039
function pods_do_shortcode( $content, $shortcodes ) {
1040
1041
	global $shortcode_tags;
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...
1042
1043
	// No shortcodes in content
1044
	if ( false === strpos( $content, '[' ) ) {
1045
		return $content;
1046
	}
1047
1048
	// No shortcodes registered
1049
	if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
1050
		return $content;
1051
	}
1052
1053
	if ( ! empty( $shortcodes ) ) {
1054
		$temp_shortcode_filter = function ( $return, $tag, $attr, $m ) use ( $shortcodes ) {
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $m. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Comprehensibility Naming introduced by
The variable name $temp_shortcode_filter exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
1055
1056
			if ( in_array( $m[2], $shortcodes, true ) ) {
1057
				// If shortcode being called is in list, return false to allow it to run
1058
				return false;
1059
			}
1060
1061
			// Return original shortcode string if we aren't going to handle at this time
1062
			return $m[0];
1063
		};
1064
		add_filter( 'pre_do_shortcode_tag', $temp_shortcode_filter, 10, 4 );
1065
	}
1066
1067
	// Build Shortcode regex pattern just for the shortcodes we want
1068
	$pattern = get_shortcode_regex();
1069
1070
	// Call shortcode callbacks just for the shortcodes we want
1071
	$content = preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
1072
1073
	if ( isset( $temp_shortcode_filter ) ) {
1074
		remove_filter( 'pre_do_shortcode_tag', $temp_shortcode_filter );
1075
	}
1076
1077
	return $content;
1078
1079
}
1080
1081
/**
1082
 * Check if Pods is compatible with WP / PHP / MySQL or not
1083
 *
1084
 * @return bool
1085
 *
1086
 * @since 1.10
1087
 */
1088
function pods_compatibility_check() {
1089
1090
	$compatible = true;
1091
1092
	if ( ! pods_version_check( 'wp', PODS_WP_VERSION_MINIMUM ) ) {
1093
		$compatible = false;
1094
1095
		add_action( 'admin_notices', 'pods_version_notice_wp' );
1096
	}
1097
1098
	if ( ! pods_version_check( 'php', PODS_PHP_VERSION_MINIMUM ) ) {
1099
		$compatible = false;
1100
1101
		add_action( 'admin_notices', 'pods_version_notice_php' );
1102
	}
1103
1104
	if ( ! pods_version_check( 'mysql', PODS_MYSQL_VERSION_MINIMUM ) ) {
1105
		$compatible = false;
1106
1107
		add_action( 'admin_notices', 'pods_version_notice_mysql' );
1108
	}
1109
1110
	return $compatible;
1111
}
1112
1113
/**
1114
 * Show WP notice if WP version is incompatible
1115
 *
1116
 * @return void
1117
 *
1118
 * @since 1.10
1119
 */
1120
function pods_version_notice_wp() {
1121
1122
	global $wp_version;
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...
1123
	?>
1124
	<div class="error fade">
1125
		<p>
1126
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
1127
			<strong>WordPress <?php echo esc_html( PODS_WP_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
1128
			<strong>WordPress <?php echo esc_html( $wp_version ); ?></strong> - <?php _e( 'Please upgrade your WordPress to continue.', 'pods' ); ?>
1129
		</p>
1130
	</div>
1131
	<?php
1132
}
1133
1134
/**
1135
 * Show WP notice if PHP version is incompatible
1136
 *
1137
 * @return void
1138
 *
1139
 * @since 1.10
1140
 */
1141
function pods_version_notice_php() {
1142
1143
	?>
1144
	<div class="error fade">
1145
		<p>
1146
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
1147
			<strong>PHP <?php echo esc_html( PODS_PHP_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
1148
			<strong>PHP <?php echo esc_html( phpversion() ); ?></strong> - <?php _e( 'Please upgrade (or have your Hosting Provider upgrade it for you) your PHP version to continue.', 'pods' ); ?>
1149
		</p>
1150
	</div>
1151
	<?php
1152
}
1153
1154
/**
1155
 * Show WP notice if MySQL version is incompatible
1156
 *
1157
 * @return void
1158
 *
1159
 * @since 1.10
1160
 */
1161
function pods_version_notice_mysql() {
1162
1163
	global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

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

1. Pass all data via parameters

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

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

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

    public function myFunction() {
        // Do something
    }
}
Loading history...
1164
	$mysql = $wpdb->db_version();
1165
	?>
1166
	<div class="error fade">
1167
		<p>
1168
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
1169
			<strong>MySQL <?php echo esc_html( PODS_MYSQL_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
1170
			<strong>MySQL <?php echo esc_html( $mysql ); ?></strong> - <?php _e( 'Please upgrade (or have your Hosting Provider upgrade it for you) your MySQL version to continue.', 'pods' ); ?>
1171
		</p>
1172
	</div>
1173
	<?php
1174
}
1175
1176
/**
1177
 * Check if a Function exists or File exists in Theme / Child Theme
1178
 *
1179
 * @param string $function_or_file Function or file name to look for.
1180
 * @param string $function_name    (optional) Function name to look for.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $function_name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1181
 * @param string $file_dir         (optional) Drectory to look into
0 ignored issues
show
Documentation introduced by
Should the type for parameter $file_dir not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1182
 * @param string $file_name        (optional) Filename to look for
0 ignored issues
show
Documentation introduced by
Should the type for parameter $file_name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1183
 *
1184
 * @return mixed
1185
 *
1186
 * @since 1.12
1187
 */
1188
function pods_function_or_file( $function_or_file, $function_name = null, $file_dir = null, $file_name = null ) {
1189
1190
	$found            = false;
1191
	$function_or_file = (string) $function_or_file;
1192
	if ( false !== $function_name ) {
1193
		if ( null === $function_name ) {
1194
			$function_name = $function_or_file;
1195
		}
1196
		$function_name = str_replace(
1197
			array(
1198
				'__',
1199
				'__',
1200
				'__',
1201
			), '_', preg_replace( '/[^a-z^A-Z^_][^a-z^A-Z^0-9^_]*/', '_', (string) $function_name )
1202
		);
1203
		if ( function_exists( 'pods_custom_' . $function_name ) ) {
1204
			$found = array( 'function' => 'pods_custom_' . $function_name );
1205
		} elseif ( function_exists( $function_name ) ) {
1206
			$found = array( 'function' => $function_name );
1207
		}
1208
	}
1209
	if ( false !== $file_name && false === $found ) {
1210
		if ( null === $file_name ) {
1211
			$file_name = $function_or_file;
1212
		}
1213
		$file_name       = str_replace(
1214
			array(
1215
				'__',
1216
				'__',
1217
				'__',
1218
			), '_', preg_replace( '/[^a-z^A-Z^0-9^_]*/', '_', (string) $file_name )
1219
		) . '.php';
1220
		$custom_location = apply_filters( 'pods_file_directory', null, $function_or_file, $function_name, $file_dir, $file_name );
1221
		if ( defined( 'PODS_FILE_DIRECTORY' ) && false !== PODS_FILE_DIRECTORY ) {
1222
			$custom_location = PODS_FILE_DIRECTORY;
1223
		}
1224
		if ( ! empty( $custom_location ) && locate_template( trim( $custom_location, '/' ) . '/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name ) ) {
1225
			$found = array( 'file' => trim( $custom_location, '/' ) . '/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name );
1226
		} elseif ( locate_template( 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name ) ) {
1227
			$found = array( 'file' => 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name );
1228
		} elseif ( locate_template( 'pods-' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name ) ) {
1229
			$found = array( 'file' => 'pods-' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name );
1230
		} elseif ( locate_template( 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name ) ) {
1231
			$found = array( 'file' => 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name );
1232
		}
1233
	}//end if
1234
1235
	return apply_filters( 'pods_function_or_file', $found, $function_or_file, $function_name, $file_name );
1236
}
1237
1238
/**
1239
 * Redirects to another page.
1240
 *
1241
 * @param string  $location The path to redirect to
1242
 * @param int     $status   Status code to use
1243
 * @param boolean $die      If true, PHP code exection will stop
1244
 *
1245
 * @return void
1246
 *
1247
 * @since 2.0
1248
 */
1249
function pods_redirect( $location, $status = 302, $die = true ) {
1250
1251
	if ( ! headers_sent() ) {
1252
		wp_redirect( $location, $status );
1253
		if ( $die ) {
1254
			die();
1255
		}
1256
	} else {
1257
		echo '<script type="text/javascript">' . 'document.location = "' . str_replace( '&amp;', '&', esc_js( $location ) ) . '";' . '</script>';
1258
		if ( $die ) {
1259
			die();
1260
		}
1261
	}
1262
}
1263
1264
/**
1265
 * Check if a user has permission to be doing something based on standard permission options
1266
 *
1267
 * @param array $options
1268
 *
1269
 * @return bool Whether the user has permissions
1270
 *
1271
 * @since 2.0.5
1272
 */
1273
function pods_permission( $options ) {
1274
1275
	global $current_user;
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...
1276
1277
	wp_get_current_user();
1278
1279
	$permission = false;
1280
1281
	if ( isset( $options['options'] ) ) {
1282
		$options = $options['options'];
1283
	}
1284
1285
	if ( pods_is_admin() ) {
1286
		$permission = true;
1287
	} elseif ( 0 === (int) pods_v( 'restrict_role', $options, 0 ) && 0 === (int) pods_v( 'restrict_capability', $options, 0 ) && 0 === (int) pods_v( 'admin_only', $options, 0 ) ) {
1288
		$permission = true;
1289
	}
1290
1291
	if ( ! $permission && 1 === (int) pods_v( 'restrict_role', $options, 0 ) ) {
1292
		$roles = pods_v( 'roles_allowed', $options );
1293
1294
		if ( ! is_array( $roles ) ) {
1295
			$roles = explode( ',', $roles );
1296
		}
1297
1298
		$roles = array_unique( array_filter( $roles ) );
1299
1300
		foreach ( $roles as $role ) {
1301
			if ( is_user_logged_in() && in_array( $role, $current_user->roles, true ) ) {
1302
				$permission = true;
1303
1304
				break;
1305
			}
1306
		}
1307
	}
1308
1309
	if ( ! $permission && 1 === (int) pods_v( 'restrict_capability', $options, 0 ) ) {
1310
		$capabilities = pods_v( 'capability_allowed', $options );
1311
1312
		if ( ! is_array( $capabilities ) ) {
1313
			$capabilities = explode( ',', $capabilities );
1314
		}
1315
1316
		$capabilities = array_unique( array_filter( $capabilities ) );
1317
1318
		foreach ( $capabilities as $capability ) {
1319
			$must_have_capabilities = explode( '&&', $capability );
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $must_have_capabilities exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
1320
			$must_have_capabilities = array_unique( array_filter( $must_have_capabilities ) );
1321
1322
			$must_have_permission = true;
1323
1324
			foreach ( $must_have_capabilities as $must_have_capability ) {
1325
				if ( ! current_user_can( $must_have_capability ) ) {
1326
					$must_have_permission = false;
1327
1328
					break;
1329
				}
1330
			}
1331
1332
			if ( $must_have_permission && is_user_logged_in() ) {
1333
				$permission = true;
1334
1335
				break;
1336
			}
1337
		}
1338
	}//end if
1339
1340
	return $permission;
1341
}
1342
1343
/**
1344
 * Check if permissions are restricted
1345
 *
1346
 * @param array $options
1347
 *
1348
 * @return bool Whether the permissions are restricted
1349
 *
1350
 * @since 2.3.4
1351
 */
1352
function pods_has_permissions( $options ) {
1353
1354
	$permission = false;
1355
1356
	if ( isset( $options['options'] ) ) {
1357
		$options = $options['options'];
1358
	}
1359
1360
	if ( 1 === (int) pods_v( 'restrict_role', $options, 0 ) || 1 === (int) pods_v( 'restrict_capability', $options, 0 ) || 1 === (int) pods_v( 'admin_only', $options, 0 ) ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return 1 === (int) pods_...in_only', $options, 0);.
Loading history...
1361
		return true;
1362
	}
1363
1364
	return false;
1365
}
1366
1367
/**
1368
 * A fork of get_page_by_title that excludes items unavailable via access rights (by status)
1369
 *
1370
 * @see   get_page_by_title
1371
 *
1372
 * @param string       $title  Title of item to get
1373
 * @param string       $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
1374
 * @param string       $type   Post Type
1375
 * @param string|array $status Post statuses to include (default is what user has access to)
0 ignored issues
show
Documentation introduced by
Should the type for parameter $status not be string|array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1376
 *
1377
 * @return WP_Post|null WP_Post on success or null on failure
1378
 *
1379
 * @since 2.3.4
1380
 */
1381
function pods_by_title( $title, $output = OBJECT, $type = 'page', $status = null ) {
1382
1383
	// @todo support Pod item lookups, not just Post Types
1384
	/**
1385
	 * @var $wpdb WPDB
1386
	 */
1387
	global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

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

1. Pass all data via parameters

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

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

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

    public function myFunction() {
        // Do something
    }
}
Loading history...
1388
1389
	if ( empty( $status ) ) {
1390
		$status = array(
1391
			'publish',
1392
		);
1393
1394
		if ( current_user_can( 'read_private_' . $type . 's' ) ) {
1395
			$status[] = 'private';
1396
		}
1397
1398
		if ( current_user_can( 'edit_' . $type . 's' ) ) {
1399
			$status[] = 'draft';
1400
		}
1401
	}
1402
1403
	$status = (array) $status;
1404
1405
	$status_sql = ' AND `post_status` IN ( %s' . str_repeat( ', %s', count( $status ) - 1 ) . ' )';
1406
1407
	$orderby_sql = ' ORDER BY ( `post_status` = %s ) DESC' . str_repeat( ', ( `post_status` = %s ) DESC', count( $status ) - 1 ) . ', `ID` DESC';
1408
1409
	// Once for WHERE, once for ORDER BY
1410
	$prepared = array_merge( array( $title, $type ), $status, $status );
1411
1412
	$page = $wpdb->get_var( $wpdb->prepare( "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_title` = %s AND `post_type` = %s" . $status_sql . $orderby_sql, $prepared ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1413
1414
	if ( $page ) {
1415
		return get_post( pods_v( $page, 'post_id' ), $output );
1416
	}
1417
1418
	return null;
1419
}
1420
1421
/**
1422
 * Get a field value from a Pod
1423
 *
1424
 * @param string       $pod    The pod name
1425
 * @param mixed        $id     (optional) The ID or slug, to load a single record; Provide array of $params to run
1426
 *                             'find'
1427
 * @param string|array $name   The field name, or an associative array of parameters
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be string|array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1428
 * @param boolean      $single (optional) For tableless fields, to return the whole array or the just the first item
1429
 *
1430
 * @return mixed Field value
1431
 *
1432
 * @since 2.1
1433
 */
1434
function pods_field( $pod, $id = false, $name = null, $single = false ) {
1435
1436
	// allow for pods_field( 'field_name' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
1437
	if ( null === $name ) {
1438
		$name   = $pod;
1439
		$single = (boolean) $id;
1440
1441
		$pod = get_post_type();
1442
		$id  = get_the_ID();
1443
	}
1444
1445
	$pod = pods( $pod, $id );
1446
1447
	if ( is_object( $pod ) ) {
1448
		return $pod->field( $name, $single );
1449
	}
1450
1451
	return null;
1452
}
1453
1454
/**
1455
 * Get a field display value from a Pod
1456
 *
1457
 * @param string       $pod    The pod name
1458
 * @param mixed        $id     (optional) The ID or slug, to load a single record; Provide array of $params to run
1459
 *                             'find'
1460
 * @param string|array $name   The field name, or an associative array of parameters
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be string|array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1461
 * @param boolean      $single (optional) For tableless fields, to return the whole array or the just the first item
1462
 *
1463
 * @return mixed Field value
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use object|integer|double|string|null|boolean.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
1464
 *
1465
 * @since 2.1
1466
 */
1467
function pods_field_display( $pod, $id = false, $name = null, $single = false ) {
1468
1469
	// allow for pods_field_display( 'field_name' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
1470
	if ( null === $name ) {
1471
		$name   = $pod;
1472
		$single = (boolean) $id;
1473
1474
		$pod = get_post_type();
1475
		$id  = get_the_ID();
1476
	}
1477
1478
	$pod = pods( $pod, $id );
1479
1480
	if ( is_object( $pod ) ) {
1481
		return $pod->display( $name, $single );
1482
	}
1483
1484
	return null;
1485
}
1486
1487
/**
1488
 * Get a field raw value from a Pod
1489
 *
1490
 * @param string       $pod    The pod name
1491
 * @param mixed        $id     (optional) The ID or slug, to load a single record; Provide array of $params to run
1492
 *                             'find'
1493
 * @param string|array $name   The field name, or an associative array of parameters
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be string|array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1494
 * @param boolean      $single (optional) For tableless fields, to return the whole array or the just the first item
1495
 *
1496
 * @return mixed Field value
1497
 *
1498
 * @since 2.1
1499
 */
1500
function pods_field_raw( $pod, $id = false, $name = null, $single = false ) {
1501
1502
	// allow for pods_field_raw( 'field_name' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
1503
	if ( null === $name ) {
1504
		$name   = $pod;
1505
		$single = (boolean) $id;
1506
1507
		$pod = get_post_type();
1508
		$id  = get_the_ID();
1509
	}
1510
1511
	return pods( $pod, $id )->raw( $name, $single );
1512
1513
}
1514
1515
/**
1516
 * Set a cached value
1517
 *
1518
 * @see   PodsView::set
1519
 *
1520
 * @param string $key        Key for the cache
1521
 * @param mixed  $value      Value to add to the cache
1522
 * @param int    $expires    (optional) Time in seconds for the cache to expire, if 0 no expiration.
1523
 * @param string $cache_mode (optional) Decides the caching method to use for the view.
1524
 * @param string $group      (optional) Key for the group
1525
 *
1526
 * @return bool|mixed|null|string|void
1527
 *
1528
 * @since 2.0
1529
 */
1530
function pods_view_set( $key, $value, $expires = 0, $cache_mode = 'cache', $group = '' ) {
1531
1532
	require_once PODS_DIR . 'classes/PodsView.php';
1533
1534
	return PodsView::set( $key, $value, $expires, $cache_mode, $group );
1535
}
1536
1537
/**
1538
 * Get a cached value
1539
 *
1540
 * @see   PodsView::get
1541
 *
1542
 * @param string $key        Key for the cache
1543
 * @param string $cache_mode (optional) Decides the caching method to use for the view.
1544
 * @param string $group      (optional) Key for the group
1545
 * @param string $callback   (optional) Callback function to run to set the value if not cached
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1546
 *
1547
 * @return bool|mixed|null|void
1548
 *
1549
 * @since 2.0
1550
 */
1551
function pods_view_get( $key, $cache_mode = 'cache', $group = '', $callback = null ) {
1552
1553
	require_once PODS_DIR . 'classes/PodsView.php';
1554
1555
	return PodsView::get( $key, $cache_mode, $group, $callback );
1556
}
1557
1558
/**
1559
 * Clear a cached value
1560
 *
1561
 * @see   PodsView::clear
1562
 *
1563
 * @param string|bool $key        Key for the cache
1564
 * @param string      $cache_mode (optional) Decides the caching method to use for the view.
1565
 * @param string      $group      (optional) Key for the group
1566
 *
1567
 * @return bool
1568
 *
1569
 * @since 2.0
1570
 */
1571
function pods_view_clear( $key = true, $cache_mode = 'cache', $group = '' ) {
1572
1573
	require_once PODS_DIR . 'classes/PodsView.php';
1574
1575
	return PodsView::clear( $key, $cache_mode, $group );
1576
}
1577
1578
/**
1579
 * Set a cached value
1580
 *
1581
 * @see   PodsView::set
1582
 *
1583
 * @param string $key     Key for the cache
1584
 * @param mixed  $value   Value to add to the cache
1585
 * @param string $group   (optional) Key for the group
1586
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1587
 *
1588
 * @return bool|mixed|null|string|void
1589
 *
1590
 * @since 2.0
1591
 */
1592
function pods_cache_set( $key, $value, $group = '', $expires = 0 ) {
1593
1594
	return pods_view_set( $key, $value, $expires, 'cache', $group );
1595
}
1596
1597
/**
1598
 * Get a cached value
1599
 *
1600
 * @see   PodsView::get
1601
 *
1602
 * @param string $key      Key for the cache
1603
 * @param string $group    (optional) Key for the group
1604
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1605
 *
1606
 * @return bool
1607
 *
1608
 * @since 2.0
1609
 */
1610
function pods_cache_get( $key, $group = '', $callback = null ) {
1611
1612
	return pods_view_get( $key, 'cache', $group, $callback );
1613
}
1614
1615
/**
1616
 * Clear a cached value
1617
 *
1618
 * @see   PodsView::clear
1619
 *
1620
 * @param string|bool $key   Key for the cache
1621
 * @param string      $group (optional) Key for the group
1622
 *
1623
 * @return bool|mixed|null|void
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use boolean.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
1624
 *
1625
 * @since 2.0
1626
 */
1627
function pods_cache_clear( $key = true, $group = '' ) {
1628
1629
	return pods_view_clear( $key, 'cache', $group );
1630
}
1631
1632
/**
1633
 * Set a cached value
1634
 *
1635
 * @see   PodsView::set
1636
 *
1637
 * @param string $key     Key for the cache
1638
 * @param mixed  $value   Value to add to the cache
1639
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1640
 *
1641
 * @return bool|mixed|null|string|void
1642
 *
1643
 * @since 2.0
1644
 */
1645
function pods_transient_set( $key, $value, $expires = 0 ) {
1646
1647
	return pods_view_set( $key, $value, $expires, 'transient' );
1648
}
1649
1650
/**
1651
 * Get a cached value
1652
 *
1653
 * @see   PodsView::get
1654
 *
1655
 * @param string $key      Key for the cache
1656
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1657
 *
1658
 * @return bool|mixed|null|void
1659
 *
1660
 * @since 2.0
1661
 */
1662
function pods_transient_get( $key, $callback = null ) {
1663
1664
	return pods_view_get( $key, 'transient', '', $callback );
1665
}
1666
1667
/**
1668
 * Clear a cached value
1669
 *
1670
 * @see   PodsView::clear
1671
 *
1672
 * @param string|bool $key Key for the cache
1673
 *
1674
 * @return bool
1675
 *
1676
 * @since 2.0
1677
 */
1678
function pods_transient_clear( $key = true ) {
1679
1680
	return pods_view_clear( $key, 'transient' );
1681
}
1682
1683
/**
1684
 * Set a cached value
1685
 *
1686
 * @see   PodsView::set
1687
 *
1688
 * @param string $key     Key for the cache
1689
 * @param mixed  $value   Value to add to the cache
1690
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1691
 *
1692
 * @return bool|mixed|null|string|void
1693
 *
1694
 * @since 2.3.10
1695
 */
1696
function pods_site_transient_set( $key, $value, $expires = 0 ) {
1697
1698
	return pods_view_set( $key, $value, $expires, 'site-transient' );
1699
}
1700
1701
/**
1702
 * Get a cached value
1703
 *
1704
 * @see   PodsView::get
1705
 *
1706
 * @param string $key      Key for the cache
1707
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1708
 *
1709
 * @return bool|mixed|null|void
1710
 *
1711
 * @since 2.3.10
1712
 */
1713
function pods_site_transient_get( $key, $callback = null ) {
1714
1715
	return pods_view_get( $key, 'site-transient', '', $callback );
1716
}
1717
1718
/**
1719
 * Clear a cached value
1720
 *
1721
 * @see   PodsView::clear
1722
 *
1723
 * @param string|bool $key Key for the cache
1724
 *
1725
 * @return bool
1726
 *
1727
 * @since 2.3.10
1728
 */
1729
function pods_site_transient_clear( $key = true ) {
1730
1731
	return pods_view_clear( $key, 'site-transient' );
1732
}
1733
1734
/**
1735
 * Set a cached value
1736
 *
1737
 * @see   PodsView::set
1738
 *
1739
 * @param string $key     Key for the cache
1740
 * @param mixed  $value   Value to add to the cache
1741
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1742
 * @param string $group   (optional) Key for the group
1743
 *
1744
 * @return bool|mixed|null|string|void
1745
 *
1746
 * @since 2.3.10
1747
 */
1748
function pods_option_cache_set( $key, $value, $expires = 0, $group = '' ) {
1749
1750
	return pods_view_set( $key, $value, $expires, 'option-cache', $group );
1751
}
1752
1753
/**
1754
 * Get a cached value
1755
 *
1756
 * @see   PodsView::get
1757
 *
1758
 * @param string $key      Key for the cache
1759
 * @param string $group    (optional) Key for the group
1760
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
Documentation introduced by
Should the type for parameter $callback not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1761
 *
1762
 * @return bool|mixed|null|void
1763
 *
1764
 * @since 2.3.10
1765
 */
1766
function pods_option_cache_get( $key, $group = '', $callback = null ) {
1767
1768
	return pods_view_get( $key, 'option-cache', $group, $callback );
1769
}
1770
1771
/**
1772
 * Clear a cached value
1773
 *
1774
 * @see   PodsView::clear
1775
 *
1776
 * @param string|bool $key   Key for the cache
1777
 * @param string      $group (optional) Key for the group
1778
 *
1779
 * @return bool
1780
 *
1781
 * @since 2.3.10
1782
 */
1783
function pods_option_cache_clear( $key = true, $group = '' ) {
1784
1785
	return pods_view_clear( $key, 'option-cache', $group );
1786
}
1787
1788
/**
1789
 * Scope variables and include a template like get_template_part that's child-theme aware
1790
 *
1791
 * @see   get_template_part
1792
 *
1793
 * @param string|array $template Template names (see get_template_part)
1794
 * @param array        $data     Data to scope to the include
0 ignored issues
show
Documentation introduced by
Should the type for parameter $data not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1795
 * @param bool         $return   Whether to return the output (echo by default)
1796
 *
1797
 * @return string|null Template output
1798
 *
1799
 * @since 2.3.9
1800
 */
1801
function pods_template_part( $template, $data = null, $return = false ) {
1802
1803
	$part = PodsView::get_template_part( $template, $data );
1804
1805
	if ( ! $return ) {
1806
		echo $part;
1807
1808
		return null;
1809
	}
1810
1811
	return $part;
1812
}
1813
1814
/**
1815
 * Add a new Pod outside of the DB
1816
 *
1817
 * @see   PodsMeta::register
1818
 *
1819
 * @param string $type   The pod type ('post_type', 'taxonomy', 'media', 'user', 'comment')
1820
 * @param string $name   The pod name
1821
 * @param array  $object (optional) Pod array, including any 'fields' arrays
0 ignored issues
show
Documentation introduced by
Should the type for parameter $object not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1822
 *
1823
 * @return array|boolean Pod data or false if unsuccessful
0 ignored issues
show
Documentation introduced by
Should the return type not be array|integer|false? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
1824
 * @since 2.1
1825
 */
1826
function pods_register_type( $type, $name, $object = null ) {
1827
1828
	if ( empty( $object ) ) {
1829
		$object = array();
1830
	}
1831
1832
	if ( ! empty( $name ) ) {
1833
		$object['name'] = $name;
1834
	}
1835
1836
	return pods_meta()->register( $type, $object );
1837
}
1838
1839
/**
1840
 * Add a new Pod field outside of the DB
1841
 *
1842
 * @see   PodsMeta::register_field
1843
 *
1844
 * @param string|array $pod    The pod name or array of pod names
1845
 * @param string       $name   The name of the Pod
1846
 * @param array        $object (optional) Pod array, including any 'fields' arrays
0 ignored issues
show
Bug introduced by
There is no parameter named $object. 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...
1847
 *
1848
 * @return array|boolean Field data or false if unsuccessful
0 ignored issues
show
Documentation introduced by
Should the return type not be array|integer|false? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
1849
 * @since 2.1
1850
 */
1851
function pods_register_field( $pod, $name, $field = null ) {
1852
1853
	if ( empty( $field ) ) {
1854
		$field = array();
1855
	}
1856
1857
	if ( ! empty( $name ) ) {
1858
		$field['name'] = $name;
1859
	}
1860
1861
	return pods_meta()->register_field( $pod, $field );
1862
}
1863
1864
/**
1865
 * Add a new Pod field type
1866
 *
1867
 * @see   PodsForm::register_field_type
1868
 *
1869
 * @param string $type The new field type identifier
1870
 * @param string $file The new field type class file location
0 ignored issues
show
Documentation introduced by
Should the type for parameter $file not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1871
 *
1872
 * @return array Field type array
1873
 * @since 2.3
1874
 */
1875
function pods_register_field_type( $type, $file = null ) {
1876
1877
	return PodsForm::register_field_type( $type, $file );
1878
}
1879
1880
/**
1881
 * Register a related object
1882
 *
1883
 * @param string $name    Object name
1884
 * @param string $label   Object label
1885
 * @param array  $options Object options
0 ignored issues
show
Documentation introduced by
Should the type for parameter $options not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1886
 *
1887
 * @return array|boolean Object array or false if unsuccessful
1888
 * @since 2.3
1889
 */
1890
function pods_register_related_object( $name, $label, $options = null ) {
1891
1892
	return PodsForm::field_method( 'pick', 'register_related_object', $name, $label, $options );
1893
}
1894
1895
/**
1896
 * Require a component (always-on)
1897
 *
1898
 * @param string $component Component ID
1899
 *
1900
 * @return void
1901
 *
1902
 * @since 2.3
1903
 */
1904
function pods_require_component( $component ) {
1905
1906
	add_filter( 'pods_component_require_' . $component, '__return_true' );
1907
}
1908
1909
/**
1910
 * Add a meta group of fields to add/edit forms
1911
 *
1912
 * @see   PodsMeta::group_add
1913
 *
1914
 * @param string|array $pod      The pod or type of element to attach the group to.
1915
 * @param string       $label    Title of the edit screen section, visible to user.
1916
 * @param string|array $fields   Either a comma separated list of text fields or an associative array containing field
1917
 *                               information.
1918
 * @param string       $context  (optional) The part of the page where the edit screen section should be shown
1919
 *                               ('normal', 'advanced', or 'side').
1920
 * @param string       $priority (optional) The priority within the context where the boxes should show ('high',
1921
 *                               'core', 'default' or 'low').
1922
 * @param string       $type     (optional) Type of the post to attach to.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1923
 *
1924
 * @return void
1925
 *
1926
 * @since 2.0
1927
 * @link  https://pods.io/docs/pods-group-add/
1928
 */
1929
function pods_group_add( $pod, $label, $fields, $context = 'normal', $priority = 'default', $type = null ) {
1930
1931
	if ( ! is_array( $pod ) && null !== $type ) {
1932
		$pod = array(
1933
			'name' => $pod,
1934
			'type' => $type,
1935
		);
1936
	}
1937
1938
	pods_meta()->group_add( $pod, $label, $fields, $context, $priority );
1939
}
1940
1941
/**
1942
 * Check if a plugin is active on non-admin pages (is_plugin_active() only available in admin)
1943
 *
1944
 * @param string $plugin Plugin name.
1945
 *
1946
 * @return bool
1947
 *
1948
 * @since 2.0
1949
 */
1950
function pods_is_plugin_active( $plugin ) {
1951
1952
	$active = false;
1953
1954
	if ( function_exists( 'is_plugin_active' ) ) {
1955
		$active = is_plugin_active( $plugin );
1956
	}
1957
1958
	if ( ! $active ) {
1959
		$active_plugins = (array) get_option( 'active_plugins', array() );
1960
1961
		if ( in_array( $plugin, $active_plugins, true ) ) {
1962
			$active = true;
1963
		}
1964
1965
		if ( ! $active && is_multisite() ) {
1966
			$plugins = get_site_option( 'active_sitewide_plugins' );
1967
1968
			if ( isset( $plugins[ $plugin ] ) ) {
1969
				$active = true;
1970
			}
1971
		}
1972
	}
1973
1974
	return $active;
1975
}
1976
1977
/**
1978
 * Check if Pods no conflict is on or not
1979
 *
1980
 * @param string $object_type
1981
 *
1982
 * @return bool
1983
 *
1984
 * @since 2.3
1985
 */
1986
function pods_no_conflict_check( $object_type = 'post' ) {
1987
1988
	if ( 'post_type' === $object_type ) {
1989
		$object_type = 'post';
1990
	} elseif ( 'term' === $object_type ) {
1991
		$object_type = 'taxonomy';
1992
	}
1993
1994
	if ( ! class_exists( 'PodsInit' ) ) {
1995
		pods_init();
1996
	}
1997
1998
	if ( ! empty( PodsInit::$no_conflict ) && isset( PodsInit::$no_conflict[ $object_type ] ) && ! empty( PodsInit::$no_conflict[ $object_type ] ) ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !empty(\PodsInit:...onflict[$object_type]);.
Loading history...
1999
		return true;
2000
	}
2001
2002
	return false;
2003
}
2004
2005
/**
2006
 * Turn off conflicting / recursive actions for an object type that Pods hooks into
2007
 *
2008
 * @param string $object_type
0 ignored issues
show
Documentation introduced by
Should the type for parameter $object not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
2009
 * @param string $object
2010
 *
2011
 * @return bool
2012
 *
2013
 * @since 2.0
2014
 */
2015
function pods_no_conflict_on( $object_type = 'post', $object = null ) {
2016
2017
	if ( 'post_type' === $object_type ) {
2018
		$object_type = 'post';
2019
	} elseif ( 'term' === $object_type ) {
2020
		$object_type = 'taxonomy';
2021
	}
2022
2023
	if ( ! class_exists( 'PodsInit' ) ) {
2024
		pods_init();
2025
	}
2026
2027
	if ( ! empty( PodsInit::$no_conflict ) && isset( PodsInit::$no_conflict[ $object_type ] ) && ! empty( PodsInit::$no_conflict[ $object_type ] ) ) {
2028
		return true;
2029
	}
2030
2031
	if ( ! is_object( PodsInit::$meta ) ) {
2032
		return false;
2033
	}
2034
2035
	$no_conflict = array(
2036
		'filter' => array(),
2037
	);
2038
2039
	// Filters = Usually get/update/delete meta functions
2040
	// Actions = Usually insert/update/save/delete object functions
2041
	if ( 'post' === $object_type ) {
2042
		if ( apply_filters( 'pods_meta_handler', true, 'post' ) ) {
2043
			// Handle *_post_meta
2044
			if ( apply_filters( 'pods_meta_handler_get', true, 'post' ) ) {
2045
				$no_conflict['filter'] = array(
2046
					array( 'get_post_metadata', array( PodsInit::$meta, 'get_post_meta' ), 10, 4 ),
2047
				);
2048
			}
2049
2050
			if ( ! pods_tableless() ) {
2051
				$no_conflict['filter'] = array_merge(
2052
					$no_conflict['filter'], array(
2053
						array( 'add_post_metadata', array( PodsInit::$meta, 'add_post_meta' ), 10, 5 ),
2054
						array( 'update_post_metadata', array( PodsInit::$meta, 'update_post_meta' ), 10, 5 ),
2055
						array( 'delete_post_metadata', array( PodsInit::$meta, 'delete_post_meta' ), 10, 5 ),
2056
					)
2057
				);
2058
			}
2059
		}
2060
2061
		$no_conflict['action'] = array(
2062
			array( 'transition_post_status', array( PodsInit::$meta, 'save_post_detect_new' ), 10, 3 ),
2063
			array( 'save_post', array( PodsInit::$meta, 'save_post' ), 10, 2 ),
2064
			array( 'wp_insert_post_data', array( PodsInit::$meta, 'save_post_track_changed_fields' ), 10, 2 ),
2065
		);
2066
	} elseif ( 'taxonomy' === $object_type ) {
2067
		if ( apply_filters( 'pods_meta_handler', true, 'term' ) ) {
2068
			// Handle *_term_meta
2069
			if ( apply_filters( 'pods_meta_handler_get', true, 'term' ) ) {
2070
				$no_conflict['filter'] = array_merge(
2071
					$no_conflict['filter'], array(
2072
						array( 'get_term_metadata', array( PodsInit::$meta, 'get_term_meta' ), 10, 4 ),
2073
					)
2074
				);
2075
			}
2076
2077
			if ( ! pods_tableless() ) {
2078
				$no_conflict['filter'] = array_merge(
2079
					$no_conflict['filter'], array(
2080
						array( 'add_term_metadata', array( PodsInit::$meta, 'add_term_meta' ), 10, 5 ),
2081
						array( 'update_term_metadata', array( PodsInit::$meta, 'update_term_meta' ), 10, 5 ),
2082
						array( 'delete_term_metadata', array( PodsInit::$meta, 'delete_term_meta' ), 10, 5 ),
2083
					)
2084
				);
2085
			}
2086
2087
			$no_conflict['action'] = array(
2088
				array( 'edited_term', array( PodsInit::$meta, 'save_taxonomy' ), 10, 3 ),
2089
				array( 'create_term', array( PodsInit::$meta, 'save_taxonomy' ), 10, 3 ),
2090
				array( 'edit_terms', array( PodsInit::$meta, 'save_taxonomy_track_changed_fields' ), 10, 2 ),
2091
			);
2092
		}//end if
2093
	} elseif ( 'media' === $object_type ) {
2094
		$no_conflict['filter'] = array(
2095
			array( 'attachment_fields_to_save', array( PodsInit::$meta, 'save_media' ), 10, 2 ),
2096
			array( 'wp_update_attachment_metadata', array( PodsInit::$meta, 'save_media' ), 10, 2 ),
2097
			array( 'wp_insert_attachment_data', array( PodsInit::$meta, 'save_post_track_changed_fields' ), 10, 2 ),
2098
		);
2099
2100
		if ( apply_filters( 'pods_meta_handler', true, 'post' ) ) {
2101
			// Handle *_post_meta
2102
			if ( apply_filters( 'pods_meta_handler_get', true, 'post' ) ) {
2103
				$no_conflict['filter'] = array_merge(
2104
					$no_conflict['filter'], array(
2105
						array( 'get_post_metadata', array( PodsInit::$meta, 'get_post_meta' ), 10, 4 ),
2106
					)
2107
				);
2108
			}
2109
2110
			if ( ! pods_tableless() ) {
2111
				$no_conflict['filter'] = array_merge(
2112
					$no_conflict['filter'], array(
2113
						array( 'add_post_metadata', array( PodsInit::$meta, 'add_post_meta' ), 10, 5 ),
2114
						array( 'update_post_metadata', array( PodsInit::$meta, 'update_post_meta' ), 10, 5 ),
2115
						array( 'delete_post_metadata', array( PodsInit::$meta, 'delete_post_meta' ), 10, 5 ),
2116
					)
2117
				);
2118
			}
2119
2120
			$no_conflict['action'] = array();
2121
		}//end if
2122
	} elseif ( 'user' === $object_type ) {
2123
		if ( apply_filters( 'pods_meta_handler', true, 'user' ) ) {
2124
			// Handle *_term_meta
2125
			if ( apply_filters( 'pods_meta_handler_get', true, 'user' ) ) {
2126
				$no_conflict['filter'] = array(
2127
					array( 'get_user_metadata', array( PodsInit::$meta, 'get_user_meta' ), 10, 4 ),
2128
				);
2129
			}
2130
2131
			if ( ! pods_tableless() ) {
2132
				$no_conflict['filter'] = array_merge(
2133
					$no_conflict['filter'], array(
2134
						array( 'add_user_metadata', array( PodsInit::$meta, 'add_user_meta' ), 10, 5 ),
2135
						array( 'update_user_metadata', array( PodsInit::$meta, 'update_user_meta' ), 10, 5 ),
2136
						array( 'delete_user_metadata', array( PodsInit::$meta, 'delete_user_meta' ), 10, 5 ),
2137
					)
2138
				);
2139
			}
2140
		}
2141
2142
		$no_conflict['action'] = array(
2143
			array( 'user_register', array( PodsInit::$meta, 'save_user' ) ),
2144
			array( 'profile_update', array( PodsInit::$meta, 'save_user' ), 10, 2 ),
2145
			array( 'pre_user_login', array( PodsInit::$meta, 'save_user_track_changed_fields' ) ),
2146
		);
2147
	} elseif ( 'comment' === $object_type ) {
2148
		if ( apply_filters( 'pods_meta_handler', true, 'comment' ) ) {
2149
			// Handle *_term_meta
2150
			if ( apply_filters( 'pods_meta_handler_get', true, 'comment' ) ) {
2151
				$no_conflict['filter'] = array(
2152
					array( 'get_comment_metadata', array( PodsInit::$meta, 'get_comment_meta' ), 10, 4 ),
2153
				);
2154
			}
2155
2156
			if ( ! pods_tableless() ) {
2157
				$no_conflict['filter'] = array_merge(
2158
					$no_conflict['filter'], array(
2159
						array( 'add_comment_metadata', array( PodsInit::$meta, 'add_comment_meta' ), 10, 5 ),
2160
						array( 'update_comment_metadata', array( PodsInit::$meta, 'update_comment_meta' ), 10, 5 ),
2161
						array( 'delete_comment_metadata', array( PodsInit::$meta, 'delete_comment_meta' ), 10, 5 ),
2162
					)
2163
				);
2164
			}
2165
		}
2166
2167
		$no_conflict['action'] = array(
2168
			array( 'pre_comment_approved', array( PodsInit::$meta, 'validate_comment' ), 10, 2 ),
2169
			array( 'comment_post', array( PodsInit::$meta, 'save_comment' ) ),
2170
			array( 'edit_comment', array( PodsInit::$meta, 'save_comment' ) ),
2171
			array( 'wp_update_comment_data', array( PodsInit::$meta, 'save_comment_track_changed_fields' ), 10, 3 ),
2172
		);
2173
	} elseif ( 'settings' === $object_type ) {
2174
		$no_conflict['filter'] = array();
2175
2176
		// @todo Better handle settings conflicts apart from each other
2177
	}//end if
2178
2179
	$conflicted = false;
2180
2181
	foreach ( $no_conflict as $action_filter => $conflicts ) {
2182
		foreach ( $conflicts as $k => $args ) {
2183
			if ( call_user_func_array( 'has_' . $action_filter, array_slice( $args, 0, 2 ) ) ) {
2184
				call_user_func_array( 'remove_' . $action_filter, array_slice( $args, 0, 3 ) );
2185
2186
				$conflicted = true;
2187
			} else {
2188
				unset( $no_conflict[ $action_filter ][ $k ] );
2189
			}
2190
		}
2191
	}
2192
2193
	if ( $conflicted ) {
2194
		PodsInit::$no_conflict[ $object_type ] = $no_conflict;
2195
2196
		return true;
2197
	}
2198
2199
	return false;
2200
2201
}
2202
2203
/**
2204
 * Turn on actions after running code during pods_conflict
2205
 *
2206
 * @param string $object_type
2207
 *
2208
 * @return bool
2209
 *
2210
 * @since 2.0
2211
 */
2212
function pods_no_conflict_off( $object_type = 'post' ) {
2213
2214
	if ( 'post_type' === $object_type ) {
2215
		$object_type = 'post';
2216
	} elseif ( 'term' === $object_type ) {
2217
		$object_type = 'taxonomy';
2218
	}
2219
2220
	if ( ! class_exists( 'PodsInit' ) ) {
2221
		pods_init();
2222
	}
2223
2224
	if ( empty( PodsInit::$no_conflict ) || ! isset( PodsInit::$no_conflict[ $object_type ] ) || empty( PodsInit::$no_conflict[ $object_type ] ) ) {
2225
		return false;
2226
	}
2227
2228
	if ( ! is_object( PodsInit::$meta ) ) {
2229
		return false;
2230
	}
2231
2232
	$no_conflict = PodsInit::$no_conflict[ $object_type ];
2233
2234
	$conflicted = false;
2235
2236
	foreach ( $no_conflict as $action_filter => $conflicts ) {
2237
		foreach ( $conflicts as $args ) {
2238
			if ( ! call_user_func_array( 'has_' . $action_filter, array_slice( $args, 0, 2 ) ) ) {
2239
				call_user_func_array( 'add_' . $action_filter, $args );
2240
2241
				$conflicted = true;
2242
			}
2243
		}
2244
	}
2245
2246
	if ( $conflicted ) {
2247
		unset( PodsInit::$no_conflict[ $object_type ] );
2248
2249
		return true;
2250
	}
2251
2252
	return false;
2253
}
2254
2255
/**
2256
 * Safely start a new session (without whitescreening on certain hosts,
2257
 * which have no session path or isn't writable)
2258
 *
2259
 * @since 2.3.10
2260
 */
2261
function pods_session_start() {
2262
2263
	$save_path = session_save_path();
0 ignored issues
show
introduced by
The use of PHP session function session_save_path() is prohibited.
Loading history...
2264
2265
	if ( false !== headers_sent() ) {
2266
		// Check if headers were sent.
2267
		return false;
2268
	} elseif ( defined( 'PODS_SESSION_AUTO_START' ) && ! PODS_SESSION_AUTO_START ) {
2269
		// Allow for bypassing Pods session autostarting.
2270
		return false;
2271
	} elseif ( 0 === strpos( $save_path, 'tcp://' ) ) {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

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

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

Loading history...
2272
		// Allow for non-file based sessions, like Memcache.
2273
		// This is OK, but we don't want to check if file_exists on next statement.
2274
	} elseif ( empty( $save_path ) || ! @file_exists( $save_path ) || ! is_writable( $save_path ) ) {
0 ignored issues
show
Coding Style introduced by
Silencing errors is discouraged
Loading history...
introduced by
Filesystem writes are forbidden, you should not be using is_writable()
Loading history...
2275
		// Check if session path exists and can be written to, avoiding PHP fatal errors.
2276
		return false;
2277
	} elseif ( '' !== session_id() ) {
0 ignored issues
show
introduced by
The use of PHP session function session_id() is prohibited.
Loading history...
2278
		// Check if session ID is already set.
2279
		return false;
2280
	}
2281
2282
	// Start session
2283
	@session_start();
0 ignored issues
show
Coding Style introduced by
Silencing errors is discouraged
Loading history...
introduced by
The use of PHP session function session_start() is prohibited.
Loading history...
2284
2285
	return true;
2286
2287
}
2288
2289
/**
2290
 * @todo  : replace string literal with a defined constant
2291
 *
2292
 * @return bool
2293
 *
2294
 * @since 2.7
2295
 */
2296
function pods_is_modal_window() {
2297
2298
	$is_modal_window = false;
2299
2300
	if ( ! empty( $_GET['pods_modal'] ) || ! empty( $_POST['pods_modal'] ) ) {
2301
		$is_modal_window = true;
2302
	}
2303
2304
	return $is_modal_window;
2305
}
2306
2307
/**
2308
 * Check if the pod object is valid and the pod exists.
2309
 *
2310
 * @param Pods|mixed $pod The pod object or something that isn't a pod object
2311
 *
2312
 * @return bool Whether the pod object is valid and exists
2313
 *
2314
 * @since 2.7
2315
 */
2316
function pod_is_valid( $pod ) {
2317
2318
	$is_valid = false;
2319
2320
	if ( $pod && is_a( $pod, 'Pods' ) && $pod->valid() ) {
2321
		$is_valid = true;
2322
	}
2323
2324
	return $is_valid;
2325
}
2326
2327
/**
2328
 * Check if the pod object has item(s).
2329
 *
2330
 * @param Pods|mixed $pod The pod object or something that isn't a pod object
2331
 *
2332
 * @return bool Whether the pod object has items
2333
 *
2334
 * @since 2.7
2335
 */
2336
function pod_has_items( $pod ) {
2337
2338
	$has_items = false;
2339
2340
	if ( pod_is_valid( $pod ) && ( $pod->id && $pod->exists() ) || ( ! empty( $pod->params ) && 0 < $pod->total() ) ) {
2341
		$has_items = true;
2342
	}
2343
2344
	return $has_items;
2345
}
2346