Issues (2873)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/general.php (74 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

Code
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
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
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
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
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
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
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
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
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
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
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
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
		wp_enqueue_script( 'pods-qtip-init' );
493
	} elseif ( ! wp_script_is( 'pods-qtip-init', 'queue' ) && ! wp_script_is( 'pods-qtip-init', 'to_do' ) && ! wp_script_is( 'pods-qtip-init', 'done' ) ) {
494
		wp_enqueue_script( 'pods-qtip-init' );
495
	}
496
497
	if ( is_array( $text ) ) {
498
		if ( isset( $text[1] ) ) {
499
			$url = $text[1];
500
		}
501
502
		$text = $text[0];
503
	}
504
505
	if ( 'help' === $text ) {
506
		return;
507
	}
508
509
	if ( 0 < strlen( $url ) ) {
510
		$text .= '<br /><br /><a href="' . $url . '" target="_blank">' . __( 'Find out more', 'pods' ) . ' &raquo;</a>';
511
	}
512
513
	echo '<img src="' . esc_url( PODS_URL ) . 'ui/images/help.png" alt="' . esc_attr( $text ) . '" class="pods-icon pods-qtip" />';
514
}
515
516
/**
517
 * Check whether or not something is a specific version minimum and/or maximum
518
 *
519
 * @param string $minimum_version Minimum version
520
 * @param string $comparison      Comparison operator
521
 * @param string $maximum_version Maximum version
0 ignored issues
show
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...
522
 *
523
 * @return bool
524
 */
525
function pods_version_check( $what, $minimum_version, $comparison = '<=', $maximum_version = null ) {
526
527
	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...
528
529
	if ( 'php' === $what ) {
530
		$version = phpversion();
531
	} elseif ( 'mysql' === $what ) {
532
		$version = $wpdb->db_version();
533
	} else {
534
		$version = $wp_version;
535
	}
536
537
	if ( ! empty( $minimum_version ) && ! version_compare( $minimum_version, $version, $comparison ) ) {
538
		return false;
539
	}
540
541
	if ( ! empty( $maximum_version ) && ! version_compare( $version, $maximum_version, $comparison ) ) {
0 ignored issues
show
This if statement, and the following return statement can be replaced with return !(!empty($maximum...version, $comparison));.
Loading history...
542
		return false;
543
	}
544
545
	return true;
546
}
547
548
/**
549
 * Run a Pods Helper
550
 *
551
 * @param string $helper_name Helper Name
552
 * @param string $value       Value to run Helper on
0 ignored issues
show
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...
553
 * @param string $name        Field name.
0 ignored issues
show
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...
554
 *
555
 * @return bool
556
 * @since 1.7.5
557
 */
558
function pods_helper( $helper_name, $value = null, $name = null ) {
559
560
	return pods()->helper( $helper_name, $value, $name );
561
}
562
563
/**
564
 * Get the full URL of the current page
565
 *
566
 * @return string Full URL of the current page
567
 * @since 2.3
568
 */
569
function pods_current_url() {
570
571
	$url = 'http';
572
573
	if ( isset( $_SERVER['HTTPS'] ) && 'off' !== $_SERVER['HTTPS'] && 0 !== $_SERVER['HTTPS'] ) {
574
		$url = 'https';
575
	}
576
577
	$url .= '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
578
579
	return apply_filters( 'pods_current_url', $url );
580
}
581
582
/**
583
 * Find out if the current page has a valid $pods
584
 *
585
 * @param object $object The Pod Object currently checking (optional)
0 ignored issues
show
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...
586
 *
587
 * @return bool
588
 * @since 2.0
589
 */
590
function is_pod( $object = null ) {
591
592
	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...
593
594
	if ( is_object( $object ) && isset( $object->pod ) && ! empty( $object->pod ) ) {
595
		return true;
596
	} elseif ( is_object( $pods ) && isset( $pods->pod ) && ! empty( $pods->pod ) ) {
597
		return true;
598
	} elseif ( is_object( $post ) && isset( $post->post_type ) && pods_api()->pod_exists( $post->post_type, 'post_type' ) ) {
599
		return true;
600
	}
601
602
	return false;
603
}
604
605
/**
606
 * See if the current user has a certain privilege
607
 *
608
 * @param mixed  $privs  The privilege name or names (array if multiple)
609
 * @param string $method The access method ("AND", "OR")
610
 *
611
 * @return bool
612
 * @since 1.2.0
613
 */
614
function pods_access( $privs, $method = 'OR' ) {
615
616
	// Convert $privs to an array
617
	$privs = (array) $privs;
618
619
	// Convert $method to uppercase
620
	$method = strtoupper( $method );
621
622
	$check = apply_filters( 'pods_access', null, $privs, $method );
623
	if ( null !== $check && is_bool( $check ) ) {
624
		return $check;
625
	}
626
627
	if ( ! is_user_logged_in() ) {
628
		return false;
629
	}
630
631
	if ( pods_is_admin( array( 'pods', 'pods_content' ) ) ) {
632
		return true;
633
	}
634
635
	// Store approved privs when using "AND"
636
	$approved_privs = array();
637
638
	// Loop through the user's roles
639
	foreach ( $privs as $priv ) {
640
		if ( 0 === strpos( $priv, 'pod_' ) ) {
641
			$priv = pods_str_replace( 'pod_', 'pods_edit_', $priv, 1 );
642
		}
643
644
		if ( 0 === strpos( $priv, 'manage_' ) ) {
645
			$priv = pods_str_replace( 'manage_', 'pods_', $priv, 1 );
646
		}
647
648
		if ( current_user_can( $priv ) ) {
649
			if ( 'OR' === $method ) {
650
				return true;
651
			}
652
653
			$approved_privs[ $priv ] = true;
654
		}
655
	}
656
	if ( 'AND' === strtoupper( $method ) ) {
657
		foreach ( $privs as $priv ) {
658
			if ( 0 === strpos( $priv, 'pod_' ) ) {
659
				$priv = pods_str_replace( 'pod_', 'pods_edit_', $priv, 1 );
660
			}
661
662
			if ( 0 === strpos( $priv, 'manage_' ) ) {
663
				$priv = pods_str_replace( 'manage_', 'pods_', $priv, 1 );
664
			}
665
666
			if ( ! isset( $approved_privs[ $priv ] ) ) {
667
				return false;
668
			}
669
		}
670
671
		return true;
672
	}
673
674
	return false;
675
}
676
677
/**
678
 * Shortcode support for use anywhere that support WP Shortcodes
679
 *
680
 * @param array  $tags    An associative array of shortcode properties
681
 * @param string $content A string that represents a template override
0 ignored issues
show
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...
682
 *
683
 * @return string
684
 * @since 1.6.7
685
 */
686
function pods_shortcode( $tags, $content = null ) {
687
688
	if ( defined( 'PODS_DISABLE_SHORTCODE' ) && PODS_DISABLE_SHORTCODE ) {
689
		return '';
690
	}
691
692
	// For enforcing pagination parameters when not displaying pagination
693
	$page   = 1;
694
	$offset = 0;
695
696
	if ( isset( $tags['page'] ) ) {
697
		$page = (int) $tags['page'];
698
		$page = max( $page, 1 );
699
	}
700
701
	if ( isset( $tags['offset'] ) ) {
702
		$offset = (int) $tags['offset'];
703
		$offset = max( $offset, 0 );
704
	}
705
706
	$defaults = array(
707
		'use_current'         => false,
708
		'name'                => null,
709
		'id'                  => null,
710
		'slug'                => null,
711
		'select'              => null,
712
		'join'                => null,
713
		'order'               => null,
714
		'orderby'             => null,
715
		'limit'               => null,
716
		'where'               => null,
717
		'having'              => null,
718
		'groupby'             => null,
719
		'search'              => true,
720
		'pagination'          => false,
721
		'page'                => null,
722
		'offset'              => null,
723
		'filters'             => false,
724
		'filters_label'       => null,
725
		'filters_location'    => 'before',
726
		'pagination_label'    => null,
727
		'pagination_location' => 'after',
728
		'field'               => null,
729
		'col'                 => null,
730
		'template'            => null,
731
		'pods_page'           => null,
732
		'helper'              => null,
733
		'form'                => null,
734
		'fields'              => null,
735
		'label'               => null,
736
		'thank_you'           => null,
737
		'view'                => null,
738
		'cache_mode'          => 'none',
739
		'expires'             => 0,
740
		'shortcodes'          => false,
741
	);
742
743
	if ( ! empty( $tags ) ) {
744
		$tags = array_merge( $defaults, $tags );
745
	} else {
746
		$tags = $defaults;
747
	}
748
749
	$tags = apply_filters( 'pods_shortcode', $tags );
750
751
	$tags['pagination']  = filter_var( $tags['pagination'], FILTER_VALIDATE_BOOLEAN );
752
	$tags['search']      = filter_var( $tags['search'], FILTER_VALIDATE_BOOLEAN );
753
	$tags['use_current'] = filter_var( $tags['use_current'], FILTER_VALIDATE_BOOLEAN );
754
755
	if ( empty( $content ) ) {
756
		$content = null;
757
	}
758
759
	// Allow views only if not targeting a file path (must be within theme)
760
	if ( 0 < strlen( $tags['view'] ) ) {
761
		$return = '';
762
763
		if ( ! file_exists( $tags['view'] ) ) {
764
			$return = pods_view( $tags['view'], null, (int) $tags['expires'], $tags['cache_mode'], true );
765
766
			if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
767
				$return = do_shortcode( $return );
768
			}
769
		}
770
771
		return $return;
772
	}
773
774
	if ( ! $tags['use_current'] && empty( $tags['name'] ) ) {
775
		if ( in_the_loop() || is_singular() ) {
776
			$pod = pods( get_post_type(), get_the_ID(), false );
777
778
			if ( ! empty( $pod ) ) {
779
				$tags['name'] = get_post_type();
780
				$id           = $tags['id'] = get_the_ID();
781
			}
782
		}
783
784
		if ( empty( $tags['name'] ) ) {
785
			return '<p>Please provide a Pod name</p>';
786
		}
787
	}
788
789
	if ( ! empty( $tags['col'] ) ) {
790
		$tags['field'] = $tags['col'];
791
792
		unset( $tags['col'] );
793
	}
794
795
	if ( ! empty( $tags['order'] ) ) {
796
		$tags['orderby'] = $tags['order'];
797
798
		unset( $tags['order'] );
799
	}
800
801
	if ( empty( $content ) && empty( $tags['pods_page'] ) && empty( $tags['template'] ) && empty( $tags['field'] ) && empty( $tags['form'] ) ) {
802
		return '<p>Please provide either a template or field name</p>';
803
	}
804
805
	if ( ! $tags['use_current'] && ! isset( $id ) ) {
806
		// id > slug (if both exist)
807
		$id = null;
808
809
		if ( ! empty( $tags['slug'] ) ) {
810
			$id = $tags['slug'];
811
812
			if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
813
				$id = pods_evaluate_tags( $id );
814
			}
815
		}
816
817
		if ( ! empty( $tags['id'] ) ) {
818
			$id = $tags['id'];
819
820
			if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
821
				$id = pods_evaluate_tags( $id );
822
			}
823
824
			if ( is_numeric( $id ) ) {
825
				$id = absint( $id );
826
			}
827
		}
828
	}//end if
829
830
	if ( ! isset( $pod ) ) {
831
		if ( ! $tags['use_current'] ) {
832
			$pod = pods( $tags['name'], $id );
0 ignored issues
show
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...
833
		} else {
834
			$pod = pods();
835
			$id  = $pod->id();
836
		}
837
	}
838
839
	if ( empty( $pod ) || ! $pod->valid() ) {
840
		return '<p>Pod not found</p>';
841
	}
842
843
	$found = 0;
844
845
	$is_singular = ( ! empty( $id ) || $tags['use_current'] );
846
847
	if ( ! $is_singular ) {
848
		$params = array();
849
850
		if ( ! defined( 'PODS_DISABLE_SHORTCODE_SQL' ) || ! PODS_DISABLE_SHORTCODE_SQL ) {
851
			if ( 0 < strlen( $tags['orderby'] ) ) {
852
				$params['orderby'] = $tags['orderby'];
853
			}
854
855
			if ( 0 < strlen( $tags['where'] ) ) {
856
				$params['where'] = $tags['where'];
857
858
				if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
859
					$params['where'] = pods_evaluate_tags( html_entity_decode( $params['where'] ) );
860
				}
861
			}
862
863
			if ( 0 < strlen( $tags['having'] ) ) {
864
				$params['having'] = $tags['having'];
865
866
				if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
867
					$params['having'] = pods_evaluate_tags( html_entity_decode( $params['having'] ) );
868
				}
869
			}
870
871
			if ( 0 < strlen( $tags['groupby'] ) ) {
872
				$params['groupby'] = $tags['groupby'];
873
			}
874
875
			if ( 0 < strlen( $tags['select'] ) ) {
876
				$params['select'] = $tags['select'];
877
			}
878
			if ( 0 < strlen( $tags['join'] ) ) {
879
				$params['join'] = $tags['join'];
880
			}
881
		}//end if
882
883
		// Forms require params set
884
		if ( ! empty( $params ) || empty( $tags['form'] ) ) {
885
			if ( ! empty( $tags['limit'] ) ) {
886
				$params['limit'] = (int) $tags['limit'];
887
			}
888
889
			$params['search'] = $tags['search'];
890
891
			$params['pagination'] = $tags['pagination'];
892
893
			// If we aren't displaying pagination, we need to enforce page/offset
894
			if ( ! $params['pagination'] ) {
895
				$params['page']   = $page;
896
				$params['offset'] = $offset;
897
898
				// Force pagination on, we need it and we're enforcing page/offset
899
				$params['pagination'] = true;
900
			} else {
901
				// If we are displaying pagination, allow page/offset override only if *set*
902
				if ( isset( $tags['page'] ) ) {
903
					$params['page'] = (int) $tags['page'];
904
					$params['page'] = max( $params['page'], 1 );
905
				}
906
907
				if ( isset( $tags['offset'] ) ) {
908
					$params['offset'] = (int) $tags['offset'];
909
					$params['offset'] = max( $params['offset'], 0 );
910
				}
911
			}
912
913
			if ( ! empty( $tags['cache_mode'] ) && 'none' !== $tags['cache_mode'] ) {
914
				$params['cache_mode'] = $tags['cache_mode'];
915
				$params['expires']    = (int) $tags['expires'];
916
			}
917
918
			$params = apply_filters( 'pods_shortcode_findrecords_params', $params, $pod, $tags );
919
920
			$pod->find( $params );
921
922
			$found = $pod->total();
923
		}//end if
924
	}//end if
925
926
	if ( ! empty( $tags['form'] ) ) {
927
		if ( 'user' === $pod->pod ) {
928
			if ( false !== strpos( $tags['fields'], '_capabilities' ) || false !== strpos( $tags['fields'], '_user_level' ) ) {
929
				// Further hardening of User-based forms
930
				return '';
931
			} elseif ( $is_singular && ( ! defined( 'PODS_SHORTCODE_ALLOW_USER_EDIT' ) || ! PODS_SHORTCODE_ALLOW_USER_EDIT ) ) {
932
				// Only explicitly allow user edit forms
933
				return '';
934
			}
935
		}
936
937
		return $pod->form( $tags['fields'], $tags['label'], $tags['thank_you'] );
938
	} elseif ( ! empty( $tags['field'] ) ) {
939
		if ( empty( $tags['helper'] ) ) {
940
			$return = $pod->display( $tags['field'] );
941
		} else {
942
			$return = $pod->helper( $tags['helper'], $pod->field( $tags['field'] ), $tags['field'] );
943
		}
944
945
		if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
946
			$return = do_shortcode( $return );
947
		}
948
949
		return $return;
950
	} elseif ( ! empty( $tags['pods_page'] ) && class_exists( 'Pods_Pages' ) ) {
951
		$pods_page = Pods_Pages::exists( $tags['pods_page'] );
952
953
		if ( empty( $pods_page ) ) {
954
			return '<p>Pods Page not found</p>';
955
		}
956
957
		$return = Pods_Pages::content( true, $pods_page );
958
959
		if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
960
			$return = do_shortcode( $return );
961
		}
962
963
		return $return;
964
	}//end if
965
966
	ob_start();
967
968
	if ( ! $is_singular && false !== $tags['filters'] && 'before' === $tags['filters_location'] ) {
969
		echo $pod->filters( $tags['filters'], $tags['filters_label'] );
0 ignored issues
show
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...
970
	}
971
972
	if ( ! $is_singular && 0 < $found && true === $tags['pagination'] && in_array(
973
		$tags['pagination_location'], array(
974
			'before',
975
			'both',
976
		), true
977
	) ) {
978
		echo $pod->pagination( $tags['pagination_label'] );
979
	}
980
981
	echo $pod->template( $tags['template'], $content );
982
983
	if ( ! $is_singular && 0 < $found && true === $tags['pagination'] && in_array(
984
		$tags['pagination_location'], array(
985
			'after',
986
			'both',
987
		), true
988
	) ) {
989
		echo $pod->pagination( $tags['pagination_label'] );
990
	}
991
992
	if ( ! $is_singular && false !== $tags['filters'] && 'after' === $tags['filters_location'] ) {
993
		echo $pod->filters( $tags['filters'], $tags['filters_label'] );
0 ignored issues
show
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...
994
	}
995
996
	$return = ob_get_clean();
997
998
	if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
999
		$return = do_shortcode( $return );
1000
	}
1001
1002
	return $return;
1003
}
1004
1005
/**
1006
 * Form Shortcode support for use anywhere that support WP Shortcodes
1007
 *
1008
 * @param array  $tags    An associative array of shortcode properties
1009
 * @param string $content Not currently used
0 ignored issues
show
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...
1010
 *
1011
 * @return string
1012
 * @since 2.3
1013
 */
1014
function pods_shortcode_form( $tags, $content = null ) {
1015
1016
	$tags['form'] = 1;
1017
1018
	return pods_shortcode( $tags );
1019
}
1020
1021
/**
1022
 * Fork of WordPress do_shortcode that allows specifying which shortcodes are ran.
1023
 *
1024
 * Search content for shortcodes and filter shortcodes through their hooks.
1025
 *
1026
 * If there are no shortcode tags defined, then the content will be returned
1027
 * without any filtering. This might cause issues when plugins are disabled but
1028
 * the shortcode will still show up in the post or content.
1029
 *
1030
 * @since 2.4.3
1031
 *
1032
 * @uses  $shortcode_tags
1033
 * @uses  get_shortcode_regex() Gets the search pattern for searching shortcodes.
1034
 *
1035
 * @param string $content    Content to search for shortcodes
1036
 * @param array  $shortcodes Array of shortcodes to run
1037
 *
1038
 * @return string Content with shortcodes filtered out.
1039
 */
1040
function pods_do_shortcode( $content, $shortcodes ) {
1041
1042
	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...
1043
1044
	// No shortcodes in content
1045
	if ( false === strpos( $content, '[' ) ) {
1046
		return $content;
1047
	}
1048
1049
	// No shortcodes registered
1050
	if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
1051
		return $content;
1052
	}
1053
1054
	if ( ! empty( $shortcodes ) ) {
1055
		$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...
1056
1057
			if ( in_array( $m[2], $shortcodes, true ) ) {
1058
				// If shortcode being called is in list, return false to allow it to run
1059
				return false;
1060
			}
1061
1062
			// Return original shortcode string if we aren't going to handle at this time
1063
			return $m[0];
1064
		};
1065
		add_filter( 'pre_do_shortcode_tag', $temp_shortcode_filter, 10, 4 );
1066
	}
1067
1068
	// Build Shortcode regex pattern just for the shortcodes we want
1069
	$pattern = get_shortcode_regex();
1070
1071
	// Call shortcode callbacks just for the shortcodes we want
1072
	$content = preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
1073
1074
	if ( isset( $temp_shortcode_filter ) ) {
1075
		remove_filter( 'pre_do_shortcode_tag', $temp_shortcode_filter );
1076
	}
1077
1078
	return $content;
1079
1080
}
1081
1082
/**
1083
 * Check if Pods is compatible with WP / PHP / MySQL or not
1084
 *
1085
 * @return bool
1086
 *
1087
 * @since 1.10
1088
 */
1089
function pods_compatibility_check() {
1090
1091
	$compatible = true;
1092
1093
	if ( ! pods_version_check( 'wp', PODS_WP_VERSION_MINIMUM ) ) {
1094
		$compatible = false;
1095
1096
		add_action( 'admin_notices', 'pods_version_notice_wp' );
1097
	}
1098
1099
	if ( ! pods_version_check( 'php', PODS_PHP_VERSION_MINIMUM ) ) {
1100
		$compatible = false;
1101
1102
		add_action( 'admin_notices', 'pods_version_notice_php' );
1103
	}
1104
1105
	if ( ! pods_version_check( 'mysql', PODS_MYSQL_VERSION_MINIMUM ) ) {
1106
		$compatible = false;
1107
1108
		add_action( 'admin_notices', 'pods_version_notice_mysql' );
1109
	}
1110
1111
	return $compatible;
1112
}
1113
1114
/**
1115
 * Show WP notice if WP version is incompatible
1116
 *
1117
 * @return void
1118
 *
1119
 * @since 1.10
1120
 */
1121
function pods_version_notice_wp() {
1122
1123
	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...
1124
	?>
1125
	<div class="error fade">
1126
		<p>
1127
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
1128
			<strong>WordPress <?php echo esc_html( PODS_WP_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
1129
			<strong>WordPress <?php echo esc_html( $wp_version ); ?></strong> - <?php _e( 'Please upgrade your WordPress to continue.', 'pods' ); ?>
1130
		</p>
1131
	</div>
1132
	<?php
1133
}
1134
1135
/**
1136
 * Show WP notice if PHP version is incompatible
1137
 *
1138
 * @return void
1139
 *
1140
 * @since 1.10
1141
 */
1142
function pods_version_notice_php() {
1143
1144
	?>
1145
	<div class="error fade">
1146
		<p>
1147
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
1148
			<strong>PHP <?php echo esc_html( PODS_PHP_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
1149
			<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' ); ?>
1150
		</p>
1151
	</div>
1152
	<?php
1153
}
1154
1155
/**
1156
 * Show WP notice if MySQL version is incompatible
1157
 *
1158
 * @return void
1159
 *
1160
 * @since 1.10
1161
 */
1162
function pods_version_notice_mysql() {
1163
1164
	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...
1165
	$mysql = $wpdb->db_version();
1166
	?>
1167
	<div class="error fade">
1168
		<p>
1169
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
1170
			<strong>MySQL <?php echo esc_html( PODS_MYSQL_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
1171
			<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' ); ?>
1172
		</p>
1173
	</div>
1174
	<?php
1175
}
1176
1177
/**
1178
 * Check if a Function exists or File exists in Theme / Child Theme
1179
 *
1180
 * @param string $function_or_file Function or file name to look for.
1181
 * @param string $function_name    (optional) Function name to look for.
0 ignored issues
show
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...
1182
 * @param string $file_dir         (optional) Drectory to look into
0 ignored issues
show
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...
1183
 * @param string $file_name        (optional) Filename to look for
0 ignored issues
show
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...
1184
 *
1185
 * @return mixed
1186
 *
1187
 * @since 1.12
1188
 */
1189
function pods_function_or_file( $function_or_file, $function_name = null, $file_dir = null, $file_name = null ) {
1190
1191
	$found            = false;
1192
	$function_or_file = (string) $function_or_file;
1193
	if ( false !== $function_name ) {
1194
		if ( null === $function_name ) {
1195
			$function_name = $function_or_file;
1196
		}
1197
		$function_name = str_replace(
1198
			array(
1199
				'__',
1200
				'__',
1201
				'__',
1202
			), '_', preg_replace( '/[^a-z^A-Z^_][^a-z^A-Z^0-9^_]*/', '_', (string) $function_name )
1203
		);
1204
		if ( function_exists( 'pods_custom_' . $function_name ) ) {
1205
			$found = array( 'function' => 'pods_custom_' . $function_name );
1206
		} elseif ( function_exists( $function_name ) ) {
1207
			$found = array( 'function' => $function_name );
1208
		}
1209
	}
1210
	if ( false !== $file_name && false === $found ) {
1211
		if ( null === $file_name ) {
1212
			$file_name = $function_or_file;
1213
		}
1214
		$file_name       = str_replace(
1215
			array(
1216
				'__',
1217
				'__',
1218
				'__',
1219
			), '_', preg_replace( '/[^a-z^A-Z^0-9^_]*/', '_', (string) $file_name )
1220
		) . '.php';
1221
		$custom_location = apply_filters( 'pods_file_directory', null, $function_or_file, $function_name, $file_dir, $file_name );
1222
		if ( defined( 'PODS_FILE_DIRECTORY' ) && false !== PODS_FILE_DIRECTORY ) {
1223
			$custom_location = PODS_FILE_DIRECTORY;
1224
		}
1225
		if ( ! empty( $custom_location ) && locate_template( trim( $custom_location, '/' ) . '/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name ) ) {
1226
			$found = array( 'file' => trim( $custom_location, '/' ) . '/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name );
1227
		} elseif ( locate_template( 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name ) ) {
1228
			$found = array( 'file' => 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name );
1229
		} elseif ( locate_template( 'pods-' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name ) ) {
1230
			$found = array( 'file' => 'pods-' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name );
1231
		} elseif ( locate_template( 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name ) ) {
1232
			$found = array( 'file' => 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name );
1233
		}
1234
	}//end if
1235
1236
	return apply_filters( 'pods_function_or_file', $found, $function_or_file, $function_name, $file_name );
1237
}
1238
1239
/**
1240
 * Redirects to another page.
1241
 *
1242
 * @param string  $location The path to redirect to
1243
 * @param int     $status   Status code to use
1244
 * @param boolean $die      If true, PHP code exection will stop
1245
 *
1246
 * @return void
1247
 *
1248
 * @since 2.0
1249
 */
1250
function pods_redirect( $location, $status = 302, $die = true ) {
1251
1252
	if ( ! headers_sent() ) {
1253
		wp_redirect( $location, $status );
1254
		if ( $die ) {
1255
			die();
1256
		}
1257
	} else {
1258
		echo '<script type="text/javascript">' . 'document.location = "' . str_replace( '&amp;', '&', esc_js( $location ) ) . '";' . '</script>';
1259
		if ( $die ) {
1260
			die();
1261
		}
1262
	}
1263
}
1264
1265
/**
1266
 * Check if a user has permission to be doing something based on standard permission options
1267
 *
1268
 * @param array $options
1269
 *
1270
 * @return bool Whether the user has permissions
1271
 *
1272
 * @since 2.0.5
1273
 */
1274
function pods_permission( $options ) {
1275
1276
	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...
1277
1278
	wp_get_current_user();
1279
1280
	$permission = false;
1281
1282
	if ( isset( $options['options'] ) ) {
1283
		$options = $options['options'];
1284
	}
1285
1286
	if ( pods_is_admin() ) {
1287
		$permission = true;
1288
	} 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 ) ) {
1289
		$permission = true;
1290
	}
1291
1292
	if ( ! $permission && 1 === (int) pods_v( 'restrict_role', $options, 0 ) ) {
1293
		$roles = pods_v( 'roles_allowed', $options );
1294
1295
		if ( ! is_array( $roles ) ) {
1296
			$roles = explode( ',', $roles );
1297
		}
1298
1299
		$roles = array_unique( array_filter( $roles ) );
1300
1301
		foreach ( $roles as $role ) {
1302
			if ( is_user_logged_in() && in_array( $role, $current_user->roles, true ) ) {
1303
				$permission = true;
1304
1305
				break;
1306
			}
1307
		}
1308
	}
1309
1310
	if ( ! $permission && 1 === (int) pods_v( 'restrict_capability', $options, 0 ) ) {
1311
		$capabilities = pods_v( 'capability_allowed', $options );
1312
1313
		if ( ! is_array( $capabilities ) ) {
1314
			$capabilities = explode( ',', $capabilities );
1315
		}
1316
1317
		$capabilities = array_unique( array_filter( $capabilities ) );
1318
1319
		foreach ( $capabilities as $capability ) {
1320
			$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...
1321
			$must_have_capabilities = array_unique( array_filter( $must_have_capabilities ) );
1322
1323
			$must_have_permission = true;
1324
1325
			foreach ( $must_have_capabilities as $must_have_capability ) {
1326
				if ( ! current_user_can( $must_have_capability ) ) {
1327
					$must_have_permission = false;
1328
1329
					break;
1330
				}
1331
			}
1332
1333
			if ( $must_have_permission && is_user_logged_in() ) {
1334
				$permission = true;
1335
1336
				break;
1337
			}
1338
		}
1339
	}//end if
1340
1341
	return $permission;
1342
}
1343
1344
/**
1345
 * Check if permissions are restricted
1346
 *
1347
 * @param array $options
1348
 *
1349
 * @return bool Whether the permissions are restricted
1350
 *
1351
 * @since 2.3.4
1352
 */
1353
function pods_has_permissions( $options ) {
1354
1355
	$permission = false;
1356
1357
	if ( isset( $options['options'] ) ) {
1358
		$options = $options['options'];
1359
	}
1360
1361
	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
This if statement, and the following return statement can be replaced with return 1 === (int) pods_...in_only', $options, 0);.
Loading history...
1362
		return true;
1363
	}
1364
1365
	return false;
1366
}
1367
1368
/**
1369
 * A fork of get_page_by_title that excludes items unavailable via access rights (by status)
1370
 *
1371
 * @see   get_page_by_title
1372
 *
1373
 * @param string       $title  Title of item to get
1374
 * @param string       $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
1375
 * @param string       $type   Post Type
1376
 * @param string|array $status Post statuses to include (default is what user has access to)
0 ignored issues
show
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...
1377
 *
1378
 * @return WP_Post|null WP_Post on success or null on failure
1379
 *
1380
 * @since 2.3.4
1381
 */
1382
function pods_by_title( $title, $output = OBJECT, $type = 'page', $status = null ) {
1383
1384
	// @todo support Pod item lookups, not just Post Types
1385
	/**
1386
	 * @var $wpdb WPDB
1387
	 */
1388
	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...
1389
1390
	if ( empty( $status ) ) {
1391
		$status = array(
1392
			'publish',
1393
		);
1394
1395
		if ( current_user_can( 'read_private_' . $type . 's' ) ) {
1396
			$status[] = 'private';
1397
		}
1398
1399
		if ( current_user_can( 'edit_' . $type . 's' ) ) {
1400
			$status[] = 'draft';
1401
		}
1402
	}
1403
1404
	$status = (array) $status;
1405
1406
	$status_sql = ' AND `post_status` IN ( %s' . str_repeat( ', %s', count( $status ) - 1 ) . ' )';
1407
1408
	$orderby_sql = ' ORDER BY ( `post_status` = %s ) DESC' . str_repeat( ', ( `post_status` = %s ) DESC', count( $status ) - 1 ) . ', `ID` DESC';
1409
1410
	// Once for WHERE, once for ORDER BY
1411
	$prepared = array_merge( array( $title, $type ), $status, $status );
1412
1413
	$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
Usage of a direct database call is discouraged.
Loading history...
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1414
1415
	if ( $page ) {
1416
		return get_post( pods_v( $page, 'post_id' ), $output );
1417
	}
1418
1419
	return null;
1420
}
1421
1422
/**
1423
 * Get a field value from a Pod
1424
 *
1425
 * @param string       $pod    The pod name
1426
 * @param mixed        $id     (optional) The ID or slug, to load a single record; Provide array of $params to run
1427
 *                             'find'
1428
 * @param string|array $name   The field name, or an associative array of parameters
0 ignored issues
show
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...
1429
 * @param boolean      $single (optional) For tableless fields, to return the whole array or the just the first item
1430
 *
1431
 * @return mixed Field value
1432
 *
1433
 * @since 2.1
1434
 */
1435
function pods_field( $pod, $id = false, $name = null, $single = false ) {
1436
1437
	// 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...
1438
	if ( null === $name ) {
1439
		$name   = $pod;
1440
		$single = (boolean) $id;
1441
1442
		$pod = get_post_type();
1443
		$id  = get_the_ID();
1444
	}
1445
1446
	$pod = pods( $pod, $id );
1447
1448
	if ( is_object( $pod ) ) {
1449
		return $pod->field( $name, $single );
1450
	}
1451
1452
	return null;
1453
}
1454
1455
/**
1456
 * Get a field display value from a Pod
1457
 *
1458
 * @param string       $pod    The pod name
1459
 * @param mixed        $id     (optional) The ID or slug, to load a single record; Provide array of $params to run
1460
 *                             'find'
1461
 * @param string|array $name   The field name, or an associative array of parameters
0 ignored issues
show
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...
1462
 * @param boolean      $single (optional) For tableless fields, to return the whole array or the just the first item
1463
 *
1464
 * @return mixed Field value
0 ignored issues
show
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...
1465
 *
1466
 * @since 2.1
1467
 */
1468
function pods_field_display( $pod, $id = false, $name = null, $single = false ) {
1469
1470
	// 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...
1471
	if ( null === $name ) {
1472
		$name   = $pod;
1473
		$single = (boolean) $id;
1474
1475
		$pod = get_post_type();
1476
		$id  = get_the_ID();
1477
	}
1478
1479
	$pod = pods( $pod, $id );
1480
1481
	if ( is_object( $pod ) ) {
1482
		return $pod->display( $name, $single );
1483
	}
1484
1485
	return null;
1486
}
1487
1488
/**
1489
 * Get a field raw value from a Pod
1490
 *
1491
 * @param string       $pod    The pod name
1492
 * @param mixed        $id     (optional) The ID or slug, to load a single record; Provide array of $params to run
1493
 *                             'find'
1494
 * @param string|array $name   The field name, or an associative array of parameters
0 ignored issues
show
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...
1495
 * @param boolean      $single (optional) For tableless fields, to return the whole array or the just the first item
1496
 *
1497
 * @return mixed Field value
1498
 *
1499
 * @since 2.1
1500
 */
1501
function pods_field_raw( $pod, $id = false, $name = null, $single = false ) {
1502
1503
	// 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...
1504
	if ( null === $name ) {
1505
		$name   = $pod;
1506
		$single = (boolean) $id;
1507
1508
		$pod = get_post_type();
1509
		$id  = get_the_ID();
1510
	}
1511
1512
	return pods( $pod, $id )->raw( $name, $single );
1513
1514
}
1515
1516
/**
1517
 * Set a cached value
1518
 *
1519
 * @see   PodsView::set
1520
 *
1521
 * @param string $key        Key for the cache
1522
 * @param mixed  $value      Value to add to the cache
1523
 * @param int    $expires    (optional) Time in seconds for the cache to expire, if 0 no expiration.
1524
 * @param string $cache_mode (optional) Decides the caching method to use for the view.
1525
 * @param string $group      (optional) Key for the group
1526
 *
1527
 * @return bool|mixed|null|string|void
1528
 *
1529
 * @since 2.0
1530
 */
1531
function pods_view_set( $key, $value, $expires = 0, $cache_mode = 'cache', $group = '' ) {
1532
1533
	require_once PODS_DIR . 'classes/PodsView.php';
1534
1535
	return PodsView::set( $key, $value, $expires, $cache_mode, $group );
1536
}
1537
1538
/**
1539
 * Get a cached value
1540
 *
1541
 * @see   PodsView::get
1542
 *
1543
 * @param string $key        Key for the cache
1544
 * @param string $cache_mode (optional) Decides the caching method to use for the view.
1545
 * @param string $group      (optional) Key for the group
1546
 * @param string $callback   (optional) Callback function to run to set the value if not cached
0 ignored issues
show
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...
1547
 *
1548
 * @return bool|mixed|null|void
1549
 *
1550
 * @since 2.0
1551
 */
1552
function pods_view_get( $key, $cache_mode = 'cache', $group = '', $callback = null ) {
1553
1554
	require_once PODS_DIR . 'classes/PodsView.php';
1555
1556
	return PodsView::get( $key, $cache_mode, $group, $callback );
1557
}
1558
1559
/**
1560
 * Clear a cached value
1561
 *
1562
 * @see   PodsView::clear
1563
 *
1564
 * @param string|bool $key        Key for the cache
1565
 * @param string      $cache_mode (optional) Decides the caching method to use for the view.
1566
 * @param string      $group      (optional) Key for the group
1567
 *
1568
 * @return bool
1569
 *
1570
 * @since 2.0
1571
 */
1572
function pods_view_clear( $key = true, $cache_mode = 'cache', $group = '' ) {
1573
1574
	require_once PODS_DIR . 'classes/PodsView.php';
1575
1576
	return PodsView::clear( $key, $cache_mode, $group );
1577
}
1578
1579
/**
1580
 * Set a cached value
1581
 *
1582
 * @see   PodsView::set
1583
 *
1584
 * @param string $key     Key for the cache
1585
 * @param mixed  $value   Value to add to the cache
1586
 * @param string $group   (optional) Key for the group
1587
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1588
 *
1589
 * @return bool|mixed|null|string|void
1590
 *
1591
 * @since 2.0
1592
 */
1593
function pods_cache_set( $key, $value, $group = '', $expires = 0 ) {
1594
1595
	return pods_view_set( $key, $value, $expires, 'cache', $group );
1596
}
1597
1598
/**
1599
 * Get a cached value
1600
 *
1601
 * @see   PodsView::get
1602
 *
1603
 * @param string $key      Key for the cache
1604
 * @param string $group    (optional) Key for the group
1605
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
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...
1606
 *
1607
 * @return bool
1608
 *
1609
 * @since 2.0
1610
 */
1611
function pods_cache_get( $key, $group = '', $callback = null ) {
1612
1613
	return pods_view_get( $key, 'cache', $group, $callback );
1614
}
1615
1616
/**
1617
 * Clear a cached value
1618
 *
1619
 * @see   PodsView::clear
1620
 *
1621
 * @param string|bool $key   Key for the cache
1622
 * @param string      $group (optional) Key for the group
1623
 *
1624
 * @return bool|mixed|null|void
0 ignored issues
show
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...
1625
 *
1626
 * @since 2.0
1627
 */
1628
function pods_cache_clear( $key = true, $group = '' ) {
1629
1630
	return pods_view_clear( $key, 'cache', $group );
1631
}
1632
1633
/**
1634
 * Set a cached value
1635
 *
1636
 * @see   PodsView::set
1637
 *
1638
 * @param string $key     Key for the cache
1639
 * @param mixed  $value   Value to add to the cache
1640
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1641
 *
1642
 * @return bool|mixed|null|string|void
1643
 *
1644
 * @since 2.0
1645
 */
1646
function pods_transient_set( $key, $value, $expires = 0 ) {
1647
1648
	return pods_view_set( $key, $value, $expires, 'transient' );
1649
}
1650
1651
/**
1652
 * Get a cached value
1653
 *
1654
 * @see   PodsView::get
1655
 *
1656
 * @param string $key      Key for the cache
1657
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
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...
1658
 *
1659
 * @return bool|mixed|null|void
1660
 *
1661
 * @since 2.0
1662
 */
1663
function pods_transient_get( $key, $callback = null ) {
1664
1665
	return pods_view_get( $key, 'transient', '', $callback );
1666
}
1667
1668
/**
1669
 * Clear a cached value
1670
 *
1671
 * @see   PodsView::clear
1672
 *
1673
 * @param string|bool $key Key for the cache
1674
 *
1675
 * @return bool
1676
 *
1677
 * @since 2.0
1678
 */
1679
function pods_transient_clear( $key = true ) {
1680
1681
	return pods_view_clear( $key, 'transient' );
1682
}
1683
1684
/**
1685
 * Set a cached value
1686
 *
1687
 * @see   PodsView::set
1688
 *
1689
 * @param string $key     Key for the cache
1690
 * @param mixed  $value   Value to add to the cache
1691
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1692
 *
1693
 * @return bool|mixed|null|string|void
1694
 *
1695
 * @since 2.3.10
1696
 */
1697
function pods_site_transient_set( $key, $value, $expires = 0 ) {
1698
1699
	return pods_view_set( $key, $value, $expires, 'site-transient' );
1700
}
1701
1702
/**
1703
 * Get a cached value
1704
 *
1705
 * @see   PodsView::get
1706
 *
1707
 * @param string $key      Key for the cache
1708
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
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...
1709
 *
1710
 * @return bool|mixed|null|void
1711
 *
1712
 * @since 2.3.10
1713
 */
1714
function pods_site_transient_get( $key, $callback = null ) {
1715
1716
	return pods_view_get( $key, 'site-transient', '', $callback );
1717
}
1718
1719
/**
1720
 * Clear a cached value
1721
 *
1722
 * @see   PodsView::clear
1723
 *
1724
 * @param string|bool $key Key for the cache
1725
 *
1726
 * @return bool
1727
 *
1728
 * @since 2.3.10
1729
 */
1730
function pods_site_transient_clear( $key = true ) {
1731
1732
	return pods_view_clear( $key, 'site-transient' );
1733
}
1734
1735
/**
1736
 * Set a cached value
1737
 *
1738
 * @see   PodsView::set
1739
 *
1740
 * @param string $key     Key for the cache
1741
 * @param mixed  $value   Value to add to the cache
1742
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
1743
 * @param string $group   (optional) Key for the group
1744
 *
1745
 * @return bool|mixed|null|string|void
1746
 *
1747
 * @since 2.3.10
1748
 */
1749
function pods_option_cache_set( $key, $value, $expires = 0, $group = '' ) {
1750
1751
	return pods_view_set( $key, $value, $expires, 'option-cache', $group );
1752
}
1753
1754
/**
1755
 * Get a cached value
1756
 *
1757
 * @see   PodsView::get
1758
 *
1759
 * @param string $key      Key for the cache
1760
 * @param string $group    (optional) Key for the group
1761
 * @param string $callback (optional) Callback function to run to set the value if not cached
0 ignored issues
show
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...
1762
 *
1763
 * @return bool|mixed|null|void
1764
 *
1765
 * @since 2.3.10
1766
 */
1767
function pods_option_cache_get( $key, $group = '', $callback = null ) {
1768
1769
	return pods_view_get( $key, 'option-cache', $group, $callback );
1770
}
1771
1772
/**
1773
 * Clear a cached value
1774
 *
1775
 * @see   PodsView::clear
1776
 *
1777
 * @param string|bool $key   Key for the cache
1778
 * @param string      $group (optional) Key for the group
1779
 *
1780
 * @return bool
1781
 *
1782
 * @since 2.3.10
1783
 */
1784
function pods_option_cache_clear( $key = true, $group = '' ) {
1785
1786
	return pods_view_clear( $key, 'option-cache', $group );
1787
}
1788
1789
/**
1790
 * Scope variables and include a template like get_template_part that's child-theme aware
1791
 *
1792
 * @see   get_template_part
1793
 *
1794
 * @param string|array $template Template names (see get_template_part)
1795
 * @param array        $data     Data to scope to the include
0 ignored issues
show
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...
1796
 * @param bool         $return   Whether to return the output (echo by default)
1797
 *
1798
 * @return string|null Template output
1799
 *
1800
 * @since 2.3.9
1801
 */
1802
function pods_template_part( $template, $data = null, $return = false ) {
1803
1804
	$part = PodsView::get_template_part( $template, $data );
1805
1806
	if ( ! $return ) {
1807
		echo $part;
1808
1809
		return null;
1810
	}
1811
1812
	return $part;
1813
}
1814
1815
/**
1816
 * Add a new Pod outside of the DB
1817
 *
1818
 * @see   PodsMeta::register
1819
 *
1820
 * @param string $type   The pod type ('post_type', 'taxonomy', 'media', 'user', 'comment')
1821
 * @param string $name   The pod name
1822
 * @param array  $object (optional) Pod array, including any 'fields' arrays
0 ignored issues
show
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...
1823
 *
1824
 * @return array|boolean Pod data or false if unsuccessful
0 ignored issues
show
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...
1825
 * @since 2.1
1826
 */
1827
function pods_register_type( $type, $name, $object = null ) {
1828
1829
	if ( empty( $object ) ) {
1830
		$object = array();
1831
	}
1832
1833
	if ( ! empty( $name ) ) {
1834
		$object['name'] = $name;
1835
	}
1836
1837
	return pods_meta()->register( $type, $object );
1838
}
1839
1840
/**
1841
 * Add a new Pod field outside of the DB
1842
 *
1843
 * @see   PodsMeta::register_field
1844
 *
1845
 * @param string|array $pod    The pod name or array of pod names
1846
 * @param string       $name   The name of the Pod
1847
 * @param array        $object (optional) Pod array, including any 'fields' arrays
0 ignored issues
show
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...
1848
 *
1849
 * @return array|boolean Field data or false if unsuccessful
0 ignored issues
show
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...
1850
 * @since 2.1
1851
 */
1852
function pods_register_field( $pod, $name, $field = null ) {
1853
1854
	if ( empty( $field ) ) {
1855
		$field = array();
1856
	}
1857
1858
	if ( ! empty( $name ) ) {
1859
		$field['name'] = $name;
1860
	}
1861
1862
	return pods_meta()->register_field( $pod, $field );
1863
}
1864
1865
/**
1866
 * Add a new Pod field type
1867
 *
1868
 * @see   PodsForm::register_field_type
1869
 *
1870
 * @param string $type The new field type identifier
1871
 * @param string $file The new field type class file location
0 ignored issues
show
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...
1872
 *
1873
 * @return array Field type array
1874
 * @since 2.3
1875
 */
1876
function pods_register_field_type( $type, $file = null ) {
1877
1878
	return PodsForm::register_field_type( $type, $file );
1879
}
1880
1881
/**
1882
 * Register a related object
1883
 *
1884
 * @param string $name    Object name
1885
 * @param string $label   Object label
1886
 * @param array  $options Object options
0 ignored issues
show
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...
1887
 *
1888
 * @return array|boolean Object array or false if unsuccessful
1889
 * @since 2.3
1890
 */
1891
function pods_register_related_object( $name, $label, $options = null ) {
1892
1893
	return PodsForm::field_method( 'pick', 'register_related_object', $name, $label, $options );
1894
}
1895
1896
/**
1897
 * Require a component (always-on)
1898
 *
1899
 * @param string $component Component ID
1900
 *
1901
 * @return void
1902
 *
1903
 * @since 2.3
1904
 */
1905
function pods_require_component( $component ) {
1906
1907
	add_filter( 'pods_component_require_' . $component, '__return_true' );
1908
}
1909
1910
/**
1911
 * Add a meta group of fields to add/edit forms
1912
 *
1913
 * @see   PodsMeta::group_add
1914
 *
1915
 * @param string|array $pod      The pod or type of element to attach the group to.
1916
 * @param string       $label    Title of the edit screen section, visible to user.
1917
 * @param string|array $fields   Either a comma separated list of text fields or an associative array containing field
1918
 *                               information.
1919
 * @param string       $context  (optional) The part of the page where the edit screen section should be shown
1920
 *                               ('normal', 'advanced', or 'side').
1921
 * @param string       $priority (optional) The priority within the context where the boxes should show ('high',
1922
 *                               'core', 'default' or 'low').
1923
 * @param string       $type     (optional) Type of the post to attach to.
0 ignored issues
show
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...
1924
 *
1925
 * @return void
1926
 *
1927
 * @since 2.0
1928
 * @link  https://pods.io/docs/pods-group-add/
1929
 */
1930
function pods_group_add( $pod, $label, $fields, $context = 'normal', $priority = 'default', $type = null ) {
1931
1932
	if ( ! is_array( $pod ) && null !== $type ) {
1933
		$pod = array(
1934
			'name' => $pod,
1935
			'type' => $type,
1936
		);
1937
	}
1938
1939
	pods_meta()->group_add( $pod, $label, $fields, $context, $priority );
1940
}
1941
1942
/**
1943
 * Check if a plugin is active on non-admin pages (is_plugin_active() only available in admin)
1944
 *
1945
 * @param string $plugin Plugin name.
1946
 *
1947
 * @return bool
1948
 *
1949
 * @since 2.0
1950
 */
1951
function pods_is_plugin_active( $plugin ) {
1952
1953
	$active = false;
1954
1955
	if ( function_exists( 'is_plugin_active' ) ) {
1956
		$active = is_plugin_active( $plugin );
1957
	}
1958
1959
	if ( ! $active ) {
1960
		$active_plugins = (array) get_option( 'active_plugins', array() );
1961
1962
		if ( in_array( $plugin, $active_plugins, true ) ) {
1963
			$active = true;
1964
		}
1965
1966
		if ( ! $active && is_multisite() ) {
1967
			$plugins = get_site_option( 'active_sitewide_plugins' );
1968
1969
			if ( isset( $plugins[ $plugin ] ) ) {
1970
				$active = true;
1971
			}
1972
		}
1973
	}
1974
1975
	return $active;
1976
}
1977
1978
/**
1979
 * Check if Pods no conflict is on or not
1980
 *
1981
 * @param string $object_type
1982
 *
1983
 * @return bool
1984
 *
1985
 * @since 2.3
1986
 */
1987
function pods_no_conflict_check( $object_type = 'post' ) {
1988
1989
	if ( 'post_type' === $object_type ) {
1990
		$object_type = 'post';
1991
	} elseif ( 'term' === $object_type ) {
1992
		$object_type = 'taxonomy';
1993
	}
1994
1995
	if ( ! class_exists( 'PodsInit' ) ) {
1996
		pods_init();
1997
	}
1998
1999
	if ( ! empty( PodsInit::$no_conflict ) && isset( PodsInit::$no_conflict[ $object_type ] ) && ! empty( PodsInit::$no_conflict[ $object_type ] ) ) {
0 ignored issues
show
This if statement, and the following return statement can be replaced with return !empty(\PodsInit:...onflict[$object_type]);.
Loading history...
2000
		return true;
2001
	}
2002
2003
	return false;
2004
}
2005
2006
/**
2007
 * Turn off conflicting / recursive actions for an object type that Pods hooks into
2008
 *
2009
 * @param string $object_type
0 ignored issues
show
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...
2010
 * @param string $object
2011
 *
2012
 * @return bool
2013
 *
2014
 * @since 2.0
2015
 */
2016
function pods_no_conflict_on( $object_type = 'post', $object = null ) {
2017
2018
	if ( 'post_type' === $object_type ) {
2019
		$object_type = 'post';
2020
	} elseif ( 'term' === $object_type ) {
2021
		$object_type = 'taxonomy';
2022
	}
2023
2024
	if ( ! class_exists( 'PodsInit' ) ) {
2025
		pods_init();
2026
	}
2027
2028
	if ( ! empty( PodsInit::$no_conflict ) && isset( PodsInit::$no_conflict[ $object_type ] ) && ! empty( PodsInit::$no_conflict[ $object_type ] ) ) {
2029
		return true;
2030
	}
2031
2032
	if ( ! is_object( PodsInit::$meta ) ) {
2033
		return false;
2034
	}
2035
2036
	$no_conflict = array(
2037
		'filter' => array(),
2038
	);
2039
2040
	// Filters = Usually get/update/delete meta functions
2041
	// Actions = Usually insert/update/save/delete object functions
2042
	if ( 'post' === $object_type ) {
2043
		if ( apply_filters( 'pods_meta_handler', true, 'post' ) ) {
2044
			// Handle *_post_meta
2045
			if ( apply_filters( 'pods_meta_handler_get', true, 'post' ) ) {
2046
				$no_conflict['filter'] = array(
2047
					array( 'get_post_metadata', array( PodsInit::$meta, 'get_post_meta' ), 10, 4 ),
2048
				);
2049
			}
2050
2051
			if ( ! pods_tableless() ) {
2052
				$no_conflict['filter'] = array_merge(
2053
					$no_conflict['filter'], array(
2054
						array( 'add_post_metadata', array( PodsInit::$meta, 'add_post_meta' ), 10, 5 ),
2055
						array( 'update_post_metadata', array( PodsInit::$meta, 'update_post_meta' ), 10, 5 ),
2056
						array( 'delete_post_metadata', array( PodsInit::$meta, 'delete_post_meta' ), 10, 5 ),
2057
					)
2058
				);
2059
			}
2060
		}
2061
2062
		$no_conflict['action'] = array(
2063
			array( 'transition_post_status', array( PodsInit::$meta, 'save_post_detect_new' ), 10, 3 ),
2064
			array( 'save_post', array( PodsInit::$meta, 'save_post' ), 10, 2 ),
2065
			array( 'wp_insert_post_data', array( PodsInit::$meta, 'save_post_track_changed_fields' ), 10, 2 ),
2066
		);
2067
	} elseif ( 'taxonomy' === $object_type ) {
2068
		if ( apply_filters( 'pods_meta_handler', true, 'term' ) ) {
2069
			// Handle *_term_meta
2070
			if ( apply_filters( 'pods_meta_handler_get', true, 'term' ) ) {
2071
				$no_conflict['filter'] = array_merge(
2072
					$no_conflict['filter'], array(
2073
						array( 'get_term_metadata', array( PodsInit::$meta, 'get_term_meta' ), 10, 4 ),
2074
					)
2075
				);
2076
			}
2077
2078
			if ( ! pods_tableless() ) {
2079
				$no_conflict['filter'] = array_merge(
2080
					$no_conflict['filter'], array(
2081
						array( 'add_term_metadata', array( PodsInit::$meta, 'add_term_meta' ), 10, 5 ),
2082
						array( 'update_term_metadata', array( PodsInit::$meta, 'update_term_meta' ), 10, 5 ),
2083
						array( 'delete_term_metadata', array( PodsInit::$meta, 'delete_term_meta' ), 10, 5 ),
2084
					)
2085
				);
2086
			}
2087
2088
			$no_conflict['action'] = array(
2089
				array( 'edited_term', array( PodsInit::$meta, 'save_taxonomy' ), 10, 3 ),
2090
				array( 'create_term', array( PodsInit::$meta, 'save_taxonomy' ), 10, 3 ),
2091
				array( 'edit_terms', array( PodsInit::$meta, 'save_taxonomy_track_changed_fields' ), 10, 2 ),
2092
			);
2093
		}//end if
2094
	} elseif ( 'media' === $object_type ) {
2095
		$no_conflict['filter'] = array(
2096
			array( 'attachment_fields_to_save', array( PodsInit::$meta, 'save_media' ), 10, 2 ),
2097
			array( 'wp_update_attachment_metadata', array( PodsInit::$meta, 'save_media' ), 10, 2 ),
2098
			array( 'wp_insert_attachment_data', array( PodsInit::$meta, 'save_post_track_changed_fields' ), 10, 2 ),
2099
		);
2100
2101
		if ( apply_filters( 'pods_meta_handler', true, 'post' ) ) {
2102
			// Handle *_post_meta
2103
			if ( apply_filters( 'pods_meta_handler_get', true, 'post' ) ) {
2104
				$no_conflict['filter'] = array_merge(
2105
					$no_conflict['filter'], array(
2106
						array( 'get_post_metadata', array( PodsInit::$meta, 'get_post_meta' ), 10, 4 ),
2107
					)
2108
				);
2109
			}
2110
2111
			if ( ! pods_tableless() ) {
2112
				$no_conflict['filter'] = array_merge(
2113
					$no_conflict['filter'], array(
2114
						array( 'add_post_metadata', array( PodsInit::$meta, 'add_post_meta' ), 10, 5 ),
2115
						array( 'update_post_metadata', array( PodsInit::$meta, 'update_post_meta' ), 10, 5 ),
2116
						array( 'delete_post_metadata', array( PodsInit::$meta, 'delete_post_meta' ), 10, 5 ),
2117
					)
2118
				);
2119
			}
2120
2121
			$no_conflict['action'] = array();
2122
		}//end if
2123
	} elseif ( 'user' === $object_type ) {
2124
		if ( apply_filters( 'pods_meta_handler', true, 'user' ) ) {
2125
			// Handle *_term_meta
2126
			if ( apply_filters( 'pods_meta_handler_get', true, 'user' ) ) {
2127
				$no_conflict['filter'] = array(
2128
					array( 'get_user_metadata', array( PodsInit::$meta, 'get_user_meta' ), 10, 4 ),
2129
				);
2130
			}
2131
2132
			if ( ! pods_tableless() ) {
2133
				$no_conflict['filter'] = array_merge(
2134
					$no_conflict['filter'], array(
2135
						array( 'add_user_metadata', array( PodsInit::$meta, 'add_user_meta' ), 10, 5 ),
2136
						array( 'update_user_metadata', array( PodsInit::$meta, 'update_user_meta' ), 10, 5 ),
2137
						array( 'delete_user_metadata', array( PodsInit::$meta, 'delete_user_meta' ), 10, 5 ),
2138
					)
2139
				);
2140
			}
2141
		}
2142
2143
		$no_conflict['action'] = array(
2144
			array( 'user_register', array( PodsInit::$meta, 'save_user' ) ),
2145
			array( 'profile_update', array( PodsInit::$meta, 'save_user' ), 10, 2 ),
2146
			array( 'pre_user_login', array( PodsInit::$meta, 'save_user_track_changed_fields' ) ),
2147
		);
2148
	} elseif ( 'comment' === $object_type ) {
2149
		if ( apply_filters( 'pods_meta_handler', true, 'comment' ) ) {
2150
			// Handle *_term_meta
2151
			if ( apply_filters( 'pods_meta_handler_get', true, 'comment' ) ) {
2152
				$no_conflict['filter'] = array(
2153
					array( 'get_comment_metadata', array( PodsInit::$meta, 'get_comment_meta' ), 10, 4 ),
2154
				);
2155
			}
2156
2157
			if ( ! pods_tableless() ) {
2158
				$no_conflict['filter'] = array_merge(
2159
					$no_conflict['filter'], array(
2160
						array( 'add_comment_metadata', array( PodsInit::$meta, 'add_comment_meta' ), 10, 5 ),
2161
						array( 'update_comment_metadata', array( PodsInit::$meta, 'update_comment_meta' ), 10, 5 ),
2162
						array( 'delete_comment_metadata', array( PodsInit::$meta, 'delete_comment_meta' ), 10, 5 ),
2163
					)
2164
				);
2165
			}
2166
		}
2167
2168
		$no_conflict['action'] = array(
2169
			array( 'pre_comment_approved', array( PodsInit::$meta, 'validate_comment' ), 10, 2 ),
2170
			array( 'comment_post', array( PodsInit::$meta, 'save_comment' ) ),
2171
			array( 'edit_comment', array( PodsInit::$meta, 'save_comment' ) ),
2172
			array( 'wp_update_comment_data', array( PodsInit::$meta, 'save_comment_track_changed_fields' ), 10, 3 ),
2173
		);
2174
	} elseif ( 'settings' === $object_type ) {
2175
		$no_conflict['filter'] = array();
2176
2177
		// @todo Better handle settings conflicts apart from each other
2178
	}//end if
2179
2180
	$conflicted = false;
2181
2182
	foreach ( $no_conflict as $action_filter => $conflicts ) {
2183
		foreach ( $conflicts as $k => $args ) {
2184
			if ( call_user_func_array( 'has_' . $action_filter, array_slice( $args, 0, 2 ) ) ) {
2185
				call_user_func_array( 'remove_' . $action_filter, array_slice( $args, 0, 3 ) );
2186
2187
				$conflicted = true;
2188
			} else {
2189
				unset( $no_conflict[ $action_filter ][ $k ] );
2190
			}
2191
		}
2192
	}
2193
2194
	if ( $conflicted ) {
2195
		PodsInit::$no_conflict[ $object_type ] = $no_conflict;
2196
2197
		return true;
2198
	}
2199
2200
	return false;
2201
2202
}
2203
2204
/**
2205
 * Turn on actions after running code during pods_conflict
2206
 *
2207
 * @param string $object_type
2208
 *
2209
 * @return bool
2210
 *
2211
 * @since 2.0
2212
 */
2213
function pods_no_conflict_off( $object_type = 'post' ) {
2214
2215
	if ( 'post_type' === $object_type ) {
2216
		$object_type = 'post';
2217
	} elseif ( 'term' === $object_type ) {
2218
		$object_type = 'taxonomy';
2219
	}
2220
2221
	if ( ! class_exists( 'PodsInit' ) ) {
2222
		pods_init();
2223
	}
2224
2225
	if ( empty( PodsInit::$no_conflict ) || ! isset( PodsInit::$no_conflict[ $object_type ] ) || empty( PodsInit::$no_conflict[ $object_type ] ) ) {
2226
		return false;
2227
	}
2228
2229
	if ( ! is_object( PodsInit::$meta ) ) {
2230
		return false;
2231
	}
2232
2233
	$no_conflict = PodsInit::$no_conflict[ $object_type ];
2234
2235
	$conflicted = false;
2236
2237
	foreach ( $no_conflict as $action_filter => $conflicts ) {
2238
		foreach ( $conflicts as $args ) {
2239
			if ( ! call_user_func_array( 'has_' . $action_filter, array_slice( $args, 0, 2 ) ) ) {
2240
				call_user_func_array( 'add_' . $action_filter, $args );
2241
2242
				$conflicted = true;
2243
			}
2244
		}
2245
	}
2246
2247
	if ( $conflicted ) {
2248
		unset( PodsInit::$no_conflict[ $object_type ] );
2249
2250
		return true;
2251
	}
2252
2253
	return false;
2254
}
2255
2256
/**
2257
 * Safely start a new session (without whitescreening on certain hosts,
2258
 * which have no session path or isn't writable)
2259
 *
2260
 * @since 2.3.10
2261
 */
2262
function pods_session_start() {
2263
2264
	$save_path = session_save_path();
0 ignored issues
show
The use of PHP session function session_save_path() is prohibited.
Loading history...
2265
2266
	if ( false !== headers_sent() ) {
2267
		// Check if headers were sent.
2268
		return false;
2269
	} elseif ( defined( 'PODS_SESSION_AUTO_START' ) && ! PODS_SESSION_AUTO_START ) {
2270
		// Allow for bypassing Pods session autostarting.
2271
		return false;
2272
	} elseif ( 0 === strpos( $save_path, 'tcp://' ) ) {
0 ignored issues
show
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...
2273
		// Allow for non-file based sessions, like Memcache.
2274
		// This is OK, but we don't want to check if file_exists on next statement.
2275
	} elseif ( empty( $save_path ) || ! @file_exists( $save_path ) || ! is_writable( $save_path ) ) {
0 ignored issues
show
Silencing errors is discouraged
Loading history...
Filesystem writes are forbidden, you should not be using is_writable()
Loading history...
2276
		// Check if session path exists and can be written to, avoiding PHP fatal errors.
2277
		return false;
2278
	} elseif ( '' !== session_id() ) {
0 ignored issues
show
The use of PHP session function session_id() is prohibited.
Loading history...
2279
		// Check if session ID is already set.
2280
		return false;
2281
	}
2282
2283
	// Start session
2284
	@session_start();
0 ignored issues
show
Silencing errors is discouraged
Loading history...
The use of PHP session function session_start() is prohibited.
Loading history...
2285
2286
	return true;
2287
2288
}
2289
2290
/**
2291
 * @todo  : replace string literal with a defined constant
2292
 *
2293
 * @return bool
2294
 *
2295
 * @since 2.7
2296
 */
2297
function pods_is_modal_window() {
2298
2299
	$is_modal_window = false;
2300
2301
	if ( ! empty( $_GET['pods_modal'] ) || ! empty( $_POST['pods_modal'] ) ) {
2302
		$is_modal_window = true;
2303
	}
2304
2305
	return $is_modal_window;
2306
}
2307
2308
/**
2309
 * Check if the pod object is valid and the pod exists.
2310
 *
2311
 * @param Pods|mixed $pod The pod object or something that isn't a pod object
2312
 *
2313
 * @return bool Whether the pod object is valid and exists
2314
 *
2315
 * @since 2.7
2316
 */
2317
function pod_is_valid( $pod ) {
2318
2319
	$is_valid = false;
2320
2321
	if ( $pod && is_a( $pod, 'Pods' ) && $pod->valid() ) {
2322
		$is_valid = true;
2323
	}
2324
2325
	return $is_valid;
2326
}
2327
2328
/**
2329
 * Check if the pod object has item(s).
2330
 *
2331
 * @param Pods|mixed $pod The pod object or something that isn't a pod object
2332
 *
2333
 * @return bool Whether the pod object has items
2334
 *
2335
 * @since 2.7
2336
 */
2337
function pod_has_items( $pod ) {
2338
2339
	$has_items = false;
2340
2341
	if ( pod_is_valid( $pod ) && ( $pod->id && $pod->exists() ) || ( ! empty( $pod->params ) && 0 < $pod->total() ) ) {
2342
		$has_items = true;
2343
	}
2344
2345
	return $has_items;
2346
}
2347