HEX
Server: Apache
System: Linux od-b43f49 4.9.0-0.bpo.12-amd64 #1 SMP Debian 4.9.210-1+deb9u1~deb8u1 (2020-06-09) x86_64
User: uid181852 (181852)
PHP: 8.2.30
Disabled: passthru,exec,system,popen,shell_exec,proc_open,pcntl_exec
Upload Files
File: /home/clients/94735d3feef25fe7d1511e6bdd8b0ef6/web/wp-content/plugins/pods/includes/general.php
<?php
/**
 * @package Pods\Global\Functions\General
 */

use Pods\Admin\Settings;
use Pods\API\Whatsit\Value_Field;
use Pods\Config_Handler;
use Pods\Permissions;
use Pods\Data\Map_Field_Values;
use Pods\Whatsit;
use Pods\Whatsit\Field;
use Pods\Whatsit\Pod;
use Pods\Whatsit\Store;

/**
 * Standardize queries and error reporting. It replaces @wp_ with $wpdb->prefix.
 *
 * @see   PodsData::query
 *
 * @param string|array $sql              The SQL query or an array with the SQL query and the values to prepare.
 * @param string       $error            (optional) The failure message to use for Database errors.
 * @param string       $results_error    (optional) Throw an error if a records are found.
 * @param string       $no_results_error (optional) Throw an error if no records are found.
 *
 * @return array|bool|mixed|null|void
 * @since 2.0.0
 */
function pods_query( $sql, $error = 'Database Error', $results_error = null, $no_results_error = null ) {
	try {
		$podsdata = pods_data( null, null, true, false );
	} catch ( Exception $exception ) {
		return null;
	}

	// If the $error is the $prepare array, set the $error to the default message.
	if ( is_array( $error ) ) {
		if ( ! is_array( $sql ) ) {
			$sql = array( $sql, $error );
		}

		$error = 'Database Error';
	}

	if ( is_array( $sql ) ) {
		$sql = array_values( $sql );

		$sql[0] = apply_filters( 'pods_query_sql', $sql[0], $error, $results_error, $no_results_error );
		$sql[0] = $podsdata->get_sql( $sql[0] );
	} else {
		$sql = apply_filters( 'pods_query_sql', $sql, $error, $results_error, $no_results_error );
		$sql = $podsdata->get_sql( $sql );
	}

	if ( 1 === (int) pods_v( 'pods_debug_sql_all' ) && is_user_logged_in() && pods_is_admin( array( 'pods' ) ) ) {
		$debug_sql = $sql;

		echo '<textarea cols="100" rows="24">';

		if ( is_array( $debug_sql ) ) {
			$debug_sql = print_r( $debug_sql, true );
		}

		echo esc_textarea( $debug_sql );

		echo '</textarea>';
	}

	return PodsData::query( $sql, $error, $results_error, $no_results_error );
}

/**
 * Prepare and run the query.
 *
 * @since 2.8.22
 *
 * @see   PodsData::query
 *
 * @param string $sql              SQL Query
 * @param array  $prepare          Variables to prepare for the SQL query.
 * @param string $error            (optional) The failure message
 * @param string $results_error    (optional) Throw an error if a records are found
 * @param string $no_results_error (optional) Throw an error if no records are found
 *
 * @return array|bool|mixed|null|void
 */
function pods_query_prepare( $sql, $prepare, $error = 'Database Error', $results_error = null, $no_results_error = null ) {
	return pods_query( [ $sql, $prepare ], $error, $results_error, $no_results_error );
}

/**
 * Standardize filters / actions
 *
 * @param string $scope Scope of the filter / action (ui for PodsUI, api for PodsAPI, etc..)
 * @param string $name  Name of filter / action to run
 * @param mixed  $args  (optional) Arguments to send to filter / action
 * @param object $obj   (optional) Object to reference for filter / action
 *
 * @return mixed
 * @since 2.0.0
 * @todo  Need to figure out how to handle $scope = 'pods' for the Pods class
 */
function pods_do_hook( $scope, $name, $args = null, $obj = null ) {
	// Add filter name
	array_unshift( $args, "pods_{$scope}_{$name}" );

	// Add object
	$args[] = $obj;

	// Run apply_filters and give it all the arguments
	$args = call_user_func_array( 'apply_filters', $args );

	return $args;
}

/**
 * Message / Notice handling for Admin UI
 *
 * @param string $message The notice / error message shown.
 * @param string $type    The message type.
 * @param bool   $return  Whether to return the message.
 *
 * @return string|null The message or null if not returning.
 */
function pods_message( $message, $type = null, $return = false ) {
	if ( empty( $type ) || ! in_array( $type, array( 'notice', 'error' ), true ) ) {
		$type = 'notice';
	}

	$class = '';

	if ( 'notice' === $type ) {
		$class = 'updated';
	} elseif ( 'error' === $type ) {
		$class = 'error';
	}

	$html = '<div id="message" class="' . esc_attr( $class ) . ' fade"><p>' . $message . '</p></div>';

	if ( $return ) {
		return $html;
	}

	echo $html;
}

$GLOBALS['pods_errors'] = array();

/**
 * The default exception handler for Pods errors.
 *
 * @since 2.9.4
 *
 * @param string|array $error The error message(s) to be thrown / displayed.
 */
function pods_error_exception( $error ) {
	pods_error( $error, 'final_exception' );
}

/**
 * Error Handling which throws / displays errors
 *
 * @param string|array        $error The error message(s) to be thrown / displayed.
 * @param object|boolean|null $obj   If $obj->display_errors is set and is set to true it will display errors,
 *                                   if boolean and is set to true it will display errors.
 *
 * @return mixed
 *
 * @throws Exception Throws exception for developer-oriented error handling.
 *
 * @since 2.0.0
 */
function pods_error( $error, $obj = null ) {
	global $pods_errors;

	$display_errors = $obj;
	if ( is_object( $obj ) && isset( $obj->display_errors ) ) {
		$display_errors = $obj->display_errors;
	}

	$error_mode = 'exception';

	if ( true === $display_errors ) {
		$error_mode = 'exit';
	} elseif ( false === $display_errors ) {
		$error_mode = 'exception';
	} elseif ( is_string( $display_errors ) ) {
		$error_mode = $display_errors;
	}

	if ( is_object( $error ) && 'Exception' === get_class( $error ) ) {
		$error_mode = 'exception';

		if ( 'final_exception' === $display_errors ) {
			$error_mode = 'exit';
		}

		/** @var Exception $error */
		$error = $error->getMessage();
	}

	/**
	 * @var string $error_mode Throw an exception, exit with the message, return false, or return WP_Error
	 */
	if ( ! in_array( $error_mode, array( 'exception', 'exit', 'false', 'wp_error', 'json' ), true ) ) {
		$error_mode = 'exception';
	}

	/**
	 * When running a Pods shortcode, never exit and only return exception.
	 */
	if ( pods_doing_shortcode() ) {
		$error_mode = 'exception';
	} elseif ( pods_doing_json() ) {
		$error_mode = 'json';
	}

	/**
	 * Filter the error mode used by pods_error.
	 *
	 * @param string                     $error_mode Error mode
	 * @param string|array               $error      Error message(s)
	 * @param object|boolean|string|null $obj
	 */
	$error_mode = apply_filters( 'pods_error_mode', $error_mode, $error, $obj );

	if ( is_array( $error ) ) {
		$error = array_map( 'wp_kses_post', $error );

		if ( 1 === count( $error ) ) {
			$error = current( $error );

			// Create WP_Error for use later.
			$wp_error = new WP_Error( 'pods-error-' . md5( $error ), $error );
		} else {
			// Create WP_Error for use later.
			$wp_error = new WP_Error();

			foreach ( $error as $error_message ) {
				$wp_error->add( 'pods-error-' . md5( $error_message ), $error_message );
			}

			if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
				$error = __( 'The following issue occurred:', 'pods' ) . "\n\n- " . implode( "\n- ", $error );
			} else {
				$error = __( 'The following issues occurred:', 'pods' ) . "\n<ul><li>" . implode( "</li>\n<li>", $error ) . '</li></ul>';
			}
		}
	} else {
		if ( is_object( $error ) ) {
			$error = __( 'An unknown error has occurred', 'pods' );
		}

		$error = wp_kses_post( $error );

		// Create WP_Error for use later.
		$wp_error = new WP_Error( 'pods-error-' . md5( $error ), $error );
	}//end if

	$pods_errors = array();

	// Support testing debug messages.
	if ( function_exists( 'codecept_debug' ) ) {
		codecept_debug( 'Pods Debug Error: ' . $error );
		pods_debug( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ) );
	}

	if ( ! empty( $error ) ) {
		if ( 'exception' === $error_mode ) {
			$exception_bypass = apply_filters( 'pods_error_exception', null, $error );

			if ( null !== $exception_bypass ) {
				return $exception_bypass;
			}

			$pods_errors = $error;

			/**
			 * Allow filtering whether the fallback is enabled to catch uncaught exceptions.
			 *
			 * @since 2.8.0
			 *
			 * @param bool   $exception_fallback_enabled Whether the fallback is enabled to catch uncaught exceptions.
			 * @param string $error                      The error information.
			 */
			$exception_fallback_enabled = apply_filters( 'pods_error_exception_fallback_enabled', true, $error );

			if ( $exception_fallback_enabled ) {
				set_exception_handler( 'pods_error_exception' );
			}

			throw new Exception( $error );
		} elseif ( 'exit' === $error_mode ) {
			$die_bypass = apply_filters( 'pods_error_die', null, $error );

			if ( null !== $die_bypass ) {
				return $die_bypass;
			}

			// die with error
			if ( ! defined( 'DOING_AJAX' ) && ! headers_sent() && ( is_admin() || false !== strpos( $_SERVER['REQUEST_URI'], 'wp-comments-post.php' ) ) ) {
				wp_die( $error, '', array( 'back_link' => true ) );
			} else {
				die( sprintf( '<e>%s</e>', $error ) );
			}
		} elseif ( 'wp_error' === $error_mode ) {
			return $wp_error;
		} elseif ( 'json' === $error_mode ) {
			$meta_box_loader_compat = (int) pods_v( 'meta-box-loader', 'request', 0 );

			// Check if this is a back-compat meta box save request.
			if ( 1 === $meta_box_loader_compat ) {
				// Do not block this page.
				error_log( 'Pods Meta Save Error:' . $error );
			} else {
				wp_send_json( [
					'message' => $error,
				], 500 );
			}
		}//end if
	}//end if

	return false;
}

/**
 * Debug variable used in pods_debug to count the instances debug is used
 */
global $pods_debug;
$pods_debug = 0;
/**
 * Debugging common issues using this function saves a few lines and is compatible with
 *
 * @param mixed   $debug The error message to be thrown / displayed
 * @param boolean $die   If set to true, a die() will occur, if set to (int) 2 then a wp_die() will occur
 * @param string  $prefix
 *
 * @return void
 *
 * @since 2.0.0
 */
function pods_debug( $debug = '_null', $die = false, $prefix = '_null' ) {
	global $pods_debug;

	$pods_debug ++;

	if ( function_exists( 'codecept_debug' ) ) {
		static $timer;

		$now = microtime( true );

		if ( ! $timer ) {
			$timer = $now;
		}

		$timing = $now - $timer;

		if ( ! is_string( $debug ) ) {
			$debug = var_export( $debug, true );
		}

		codecept_debug( 'Pods Debug: ' . $debug . ' [debug timing: ' . number_format( $timing, 4 ) . 's]' );

		$timer = $now;

		return;
	}

	if ( defined( 'WP_CLI' ) ) {
		if ( ! is_string( $debug ) ) {
			$debug = var_export( $debug, true );
		}

		WP_CLI::debug( $debug );

		return;
	}

	ob_start();

	if ( '_null' !== $prefix ) {
		var_dump( $prefix );
	}

	$debug_line_number = 0;

	if ( '_null' !== $debug ) {
		var_dump( $debug );

		$debug_line_number = __LINE__ - 2;
	} else {
		var_dump( 'Pods Debug #' . $pods_debug );

		$debug_line_number = __LINE__ - 2;
	}

	$debug_line_check = sprintf(
		'<small>%s:%s:</small>',
		__FILE__,
		$debug_line_number
	);

	$debug = ob_get_clean();

	if ( false === strpos( $debug, "<pre class='xdebug-var-dump'" ) ) {
		if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
			$debug = esc_html( $debug );
		}

		$debug = '<pre>' . $debug . '</pre>';
	} elseif ( false !== strpos( $debug, $debug_line_check ) ) {
		// Attempt to replace the backtrace file/line from our var_dump() above with where the pods_debug() itself was called.
		$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );

		if ( ! empty( $backtrace[0] ) ) {
			$debug_line_replace = sprintf(
				'<small>%s:%s:</small>',
				$backtrace[0]['file'],
				$backtrace[0]['line']
			);

			$debug = str_replace( $debug_line_check, $debug_line_replace, $debug );
		}
	}

	$debug = '<e>' . $debug;

	if ( 2 === $die ) {
		wp_die( $debug, '', array( 'back_link' => true ) );
	} elseif ( true === $die ) {
		die( $debug );
	}

	echo $debug;
}

/**
 * Check if debug is enabled and should be displayed.
 *
 * @return bool
 * @since  2.7.13
 */
function pods_is_debug_display() {
	return ( WP_DEBUG && WP_DEBUG_DISPLAY );
}

/**
 * Determine if user has admin access
 *
 * @param string|array $cap Additional capabilities to check
 *
 * @return bool Whether user has admin access
 *
 * @since 2.3.5
 */
function pods_is_admin( $cap = null ) {
	if ( is_user_logged_in() ) {

		if ( is_multisite() && is_super_admin() ) {
			return apply_filters( 'pods_is_admin', true, $cap, '_super_admin' );
		}

		$pods_admin_capabilities = array();

		if ( ! is_multisite() ) {
			// Default is_super_admin() checks against this capability.
			$pods_admin_capabilities[] = 'delete_users';
		}

		$pods_admin_capabilities = apply_filters( 'pods_admin_capabilities', $pods_admin_capabilities, $cap );

		if ( empty( $cap ) ) {
			$cap = array();
		} else {
			$cap = (array) $cap;
		}

		$cap = array_unique( array_filter( array_merge( $pods_admin_capabilities, $cap ) ) );

		foreach ( $cap as $capability ) {
			if ( current_user_can( $capability ) ) {
				return apply_filters( 'pods_is_admin', true, $cap, $capability );
			}
		}
	}//end if

	return apply_filters( 'pods_is_admin', false, $cap, null );
}

/**
 * Determine if Developer Mode is enabled
 *
 * @return bool Whether Developer Mode is enabled
 *
 * @since 2.3.0
 */
function pods_developer() {
	if ( defined( 'PODS_DEVELOPER' ) && PODS_DEVELOPER ) {
		return true;
	}

	return false;
}

/**
 * Determine if Tableless Mode is enabled
 *
 * @return bool Whether Tableless Mode is enabled
 *
 * @since 2.3.0
 */
function pods_tableless() {
	if ( defined( 'PODS_TABLELESS' ) && PODS_TABLELESS ) {
		return true;
	}

	return false;
}

/**
 * Determine whether the wp_podsrel table is enabled.
 *
 * @since 2.8.0
 *
 * @param null|Field  $field   The field object.
 * @param null|string $context The context of the podsrel check (lookup/save).
 *
 * @return bool Whether the wp_podsrel table is enabled.
 */
function pods_podsrel_enabled( $field = null, $context = null ) {
	// Disabled when Pods Tableless mode is on.
	if ( pods_tableless() ) {
		return false;
	}

	/**
	 * Allow filtering of whether the wp_podsrel table is enabled.
	 *
	 * @since 2.8.0
	 *
	 * @param bool        $enabled Whether the wp_podsrel table is enabled.
	 * @param null|Field  $field   The field object.
	 * @param null|string $context The context of the podsrel check (lookup/save).
	 */
	return (bool) apply_filters( 'pods_podsrel_enabled', true, $field, $context );
}

/**
 * Determine whether relationship meta storage is enabled.
 *
 * @since 2.8.0
 *
 * @param null|array|Field $field The field object.
 * @param null|array|Pod   $pod   The pod object.
 *
 * @return bool Whether relationship meta storage is enabled.
 */
function pods_relationship_meta_storage_enabled( $field = null, $pod = null ) {
	/**
	 * Allow filtering of whether relationship meta storage is enabled.
	 *
	 * @since 2.8.0
	 *
	 * @param bool             $enabled Whether relationship meta storage table is enabled.
	 * @param null|array|Field $field   The field object.
	 * @param null|array|Pod   $pod     The pod object.
	 */
	return (bool) apply_filters( 'pods_relationship_meta_storage_enabled', true, $field, $pod );
}

/**
 * Determine whether relationship meta storage is enabled for simple relationships.
 *
 * @since 2.8.9
 *
 * @param null|array|Field $field The field object.
 * @param null|array|Pod   $pod   The pod object.
 *
 * @return bool Whether relationship meta storage is enabled.
 */
function pods_relationship_meta_storage_enabled_for_simple_relationships( $field = null, $pod = null ) {
	$enabled = null === $pod || 'meta' === $pod['storage'] || 'settings' === $pod['storage'];

	/**
	 * Allow filtering of whether relationship meta storage is enabled for simple relationships.
	 *
	 * @since 2.8.9
	 *
	 * @param bool             $enabled Whether relationship meta storage table is enabled for simple relationships.
	 * @param null|array|Field $field   The field object.
	 * @param null|array|Pod   $pod     The pod object.
	 */
	return (bool) apply_filters( 'pods_relationship_meta_storage_enabled_for_simple_relationships', $enabled, $field, $pod );
}

/**
 * Determine whether relationship table storage is enabled for simple relationships.
 *
 * @since 2.8.9
 *
 * @param null|array|Field $field The field object.
 * @param null|array|Pod   $pod   The pod object.
 *
 * @return bool Whether relationship table storage is enabled.
 */
function pods_relationship_table_storage_enabled_for_simple_relationships( $field = null, $pod = null ) {
	$enabled = null === $pod || 'table' === $pod['storage'];

	/**
	 * Allow filtering of whether relationship table storage is enabled for simple relationships.
	 *
	 * @since 2.8.9
	 *
	 * @param bool             $enabled Whether relationship table storage table is enabled for simple relationships.
	 * @param null|array|Field $field   The field object.
	 * @param null|array|Pod   $pod     The pod object.
	 */
	return (bool) apply_filters( 'pods_relationship_table_storage_enabled_for_simple_relationships', $enabled, $field, $pod );
}

/**
 * Determine whether relationship table storage is enabled for object based relationships.
 *
 * @since 2.8.16
 *
 * @param null|array|Field $field The field object.
 * @param null|array|Pod   $pod   The pod object.
 *
 * @return bool Whether relationship table storage is enabled.
 */
function pods_relationship_table_storage_enabled_for_object_relationships( $field = null, $pod = null ) {
	/**
	 * Allow filtering of whether relationship table storage is enabled for object based relationships.
	 *
	 * @since 2.8.16
	 *
	 * @param bool             $enabled Whether relationship table storage table is enabled for object based relationships.
	 * @param null|array|Field $field   The field object.
	 * @param null|array|Pod   $pod     The pod object.
	 */
	return (bool) apply_filters( 'pods_relationship_table_storage_enabled_for_object_relationships', false, $field, $pod );
}

/**
 * Determine if Light Mode is enabled
 *
 * @return bool Whether Light Mode is enabled
 *
 * @since 2.7.13
 */
function pods_light() {
	if ( defined( 'PODS_LIGHT' ) && PODS_LIGHT ) {
		return true;
	}

	return false;
}

/**
 * Determine if Strict Mode is enabled
 *
 * @param bool $include_debug Whether to include WP_DEBUG in strictness level
 *
 * @return bool Whether Strict Mode is enabled
 *
 * @since 2.3.5
 */
function pods_strict( $include_debug = true ) {
	$strict = false;

	if ( defined( 'PODS_STRICT' ) && PODS_STRICT ) {
		// Deprecated PODS_STRICT_MODE since 2.3.5
		$strict = true;
	} elseif ( defined( 'PODS_STRICT_MODE' ) && PODS_STRICT_MODE && pods_allow_deprecated( false ) ) {
		$strict = true;
	} elseif ( $include_debug && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
		$strict = true;
	}

	/**
	 * Allow filtering of whether strict mode is enabled.
	 *
	 * @param boolean $strict Whether strict mode is enabled.
	 *
	 * @since 2.8.0
	 */
	return apply_filters( 'pods_strict_mode', $strict );
}

/**
 * Determine if Deprecated Mode is enabled
 *
 * @param bool $include_debug Whether to include strict mode
 *
 * @return bool Whether Deprecated Mode is enabled
 *
 * @since 2.3.10
 */
function pods_allow_deprecated( $strict = true ) {
	if ( $strict && pods_strict( false ) ) {
		return false;
	} elseif ( ! defined( 'PODS_DEPRECATED' ) || PODS_DEPRECATED ) {
		return true;
	}

	return false;
}

/**
 * Determine if Pods API Caching is enabled
 *
 * @return bool Whether Pods API Caching is enabled
 *
 * @since 2.3.9
 */
function pods_api_cache() {
	if ( defined( 'PODS_API_CACHE' ) && ! PODS_API_CACHE ) {
		return false;
	}

	/**
	 * Filter whether to use the Pods API cache.
	 *
	 * @param boolean $use_cache Whether to use the Pods API cache.
	 *
	 * @since 2.8.0
	 */
	return apply_filters( 'pods_api_cache', true );
}

/**
 * Determine if Pods shortcodes can evaluate magic tags.
 *
 * @since 2.7.16
 *
 * @return bool
 */
function pods_shortcode_allow_evaluate_tags() {
	if ( defined( 'PODS_SHORTCODE_ALLOW_EVALUATE_TAGS' ) && PODS_SHORTCODE_ALLOW_EVALUATE_TAGS ) {
		return true;
	}

	return false;
}

/**
 * Marks a function as deprecated and informs when it has been used.
 *
 * There is a hook deprecated_function_run that will be called that can be used
 * to get the backtrace up to what file and function called the deprecated
 * function.
 *
 * The current behavior is to trigger a user error if WP_DEBUG is true.
 *
 * This function is to be used in every function that is deprecated.
 *
 * @uses  do_action() Calls 'deprecated_function_run' and passes the function name, what to use instead,
 *   and the version the function was deprecated in.
 * @uses  apply_filters() Calls 'deprecated_function_trigger_error' and expects boolean value of true to do
 *   trigger or false to not trigger error.
 *
 * @param string $function    The function that was called
 * @param string $version     The version of WordPress that deprecated the function
 * @param string $replacement Optional. The function that should have been called
 *
 * @since 2.0.0
 */
function pods_deprecated( $function, $version, $replacement = null ) {
	if ( ! version_compare( $version, PODS_VERSION, '<=' ) && ! version_compare( $version . '-a-0', PODS_VERSION, '<=' ) ) {
		return;
	}

	do_action( 'deprecated_function_run', $function, $replacement, $version );

	// Allow plugin to filter the output error trigger
	if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
		if ( ! is_null( $replacement ) ) {
			$error = __( '%1$s has been <strong>deprecated</strong> since Pods version %2$s! Use %3$s instead.', 'pods' );
		} else {
			$error = __( '%1$s has been <strong>deprecated</strong> since Pods version %2$s with no alternative available.', 'pods' );
		}

		trigger_error( sprintf( $error, $function, $version, $replacement ), E_USER_DEPRECATED );
	}
}

/**
 * Inline help
 *
 * @param string      $text      Help text.
 * @param null|string $url       Documentation URL.
 * @param null|string $container The HTML container path for where the inline help will live.
 *
 * @return void
 *
 * @since 2.0.0
 */
function pods_help( $text, $url = null, $container = null ) {
	if ( ! wp_script_is( 'jquery-qtip2', 'registered' ) ) {
		wp_register_script( 'jquery-qtip2', PODS_URL . 'ui/js/qtip/jquery.qtip.min.js', array( 'jquery' ), '3.0.3' );
		wp_enqueue_script( 'jquery-qtip2' );
	} elseif ( ! wp_script_is( 'jquery-qtip2', 'queue' ) && ! wp_script_is( 'jquery-qtip2', 'to_do' ) && ! wp_script_is( 'jquery-qtip2', 'done' ) ) {
		wp_enqueue_script( 'jquery-qtip2' );
	}

	if ( ! wp_script_is( 'pods-qtip-init', 'registered' ) ) {
		wp_register_script( 'pods-qtip-init', PODS_URL . 'ui/js/qtip.js', array(
			'jquery',
			'jquery-qtip2',
		), PODS_VERSION );
		pods_form_enqueue_script( 'pods-qtip-init' );
	} elseif ( ! wp_script_is( 'pods-qtip-init', 'queue' ) && ! wp_script_is( 'pods-qtip-init', 'to_do' ) && ! wp_script_is( 'pods-qtip-init', 'done' ) ) {
		pods_form_enqueue_script( 'pods-qtip-init' );
	}

	pods_form_enqueue_script( 'pods' );
	pods_form_enqueue_style( 'pods' );

	static $pods_qtip_added = [];

	if ( null !== $container && ! isset( $pods_qtip_added[ $container ] ) ) {
		wp_add_inline_script(
			'pods',
			"
				jQuery( function ( $ ) {
					$( document ).Pods( 'qtip', '" . esc_js( $container ) . "' );
				} );
			"
		);

		$pods_qtip_added[ $container ] = true;
	}

	if ( is_array( $text ) ) {
		if ( isset( $text[1] ) ) {
			$url = $text[1];
		}

		$text = $text[0];
	}

	if ( 'help' === $text ) {
		return;
	}

	if ( 0 < strlen( $url ) ) {
		$text .= '<br /><br /><a href="' . esc_url( $url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Find out more', 'pods' ) . ' &raquo;</a>';
	}

	echo '<img src="' . esc_url( PODS_URL ) . 'ui/images/help.png" alt="' . esc_attr( $text ) . '" class="pods-icon pods-qtip" />';
}

/**
 * Check whether something is a specific version minimum and/or maximum
 *
 * @param string $minimum_version Minimum version
 * @param string $comparison      Comparison operator
 * @param string $maximum_version Maximum version
 *
 * @return bool
 */
function pods_version_check( $what, $minimum_version, $comparison = '<=', $maximum_version = null ) {
	global $wp_version, $wpdb;

	if ( 'php' === $what ) {
		$version = phpversion();
	} elseif ( 'mysql' === $what ) {
		$version = $wpdb->db_version();
	} else {
		$version = $wp_version;
	}

	if ( ! empty( $minimum_version ) && ! version_compare( $minimum_version, $version, $comparison ) ) {
		return false;
	}

	if ( ! empty( $maximum_version ) && ! version_compare( $version, $maximum_version, $comparison ) ) {
		return false;
	}

	return true;
}

/**
 * Run a Pods Helper
 *
 * @param string $helper_name Helper Name
 * @param string $value       Value to run Helper on
 * @param string $name        Field name.
 *
 * @return bool
 * @since 1.7.5
 */
function pods_helper( $helper_name, $value = null, $name = null ) {
	return pods()->helper( $helper_name, $value, $name );
}

/**
 * Get the current hostname.
 *
 * @since 2.8.0
 *
 * @return string The current hostname.
 */
function pods_current_host() {
	if ( empty( $_SERVER['HTTP_HOST'] ) ) {
		$host = wp_parse_url( get_site_url(), PHP_URL_HOST );

		if ( empty( $host ) ) {
			return 'localhost';
		}

		return $host;
	}

	return $_SERVER['HTTP_HOST'];
}

/**
 * Get the full path of the current page.
 *
 * @since 2.8.0
 *
 * @return string Full path of the current page.
 */
function pods_current_path() {
	if ( empty( $_SERVER['REQUEST_URI'] ) ) {
		return '/';
	}

	return $_SERVER['REQUEST_URI'];
}

/**
 * Get the full URL of the current page.
 *
 * @since 2.3.0
 *
 * @return string Full URL of the current page.
 */
function pods_current_url() {
	$url = 'http';

	if ( isset( $_SERVER['HTTPS'] ) && 'off' !== $_SERVER['HTTPS'] && 0 !== $_SERVER['HTTPS'] ) {
		$url = 'https';
	}

	$url .= '://' . pods_current_host() . pods_current_path();

	return apply_filters( 'pods_current_url', $url );
}

/**
 * Find out if the current page has a valid $pods
 *
 * @param object $object The Pod Object currently checking (optional)
 *
 * @return bool
 * @since 2.0.0
 */
function is_pod( $object = null ) {
	global $pods, $post;

	if ( is_object( $object ) && isset( $object->pod ) && ! empty( $object->pod ) ) {
		return true;
	} elseif ( is_object( $pods ) && isset( $pods->pod ) && ! empty( $pods->pod ) ) {
		return true;
	} elseif ( is_object( $post ) && isset( $post->post_type ) && pods_api()->pod_exists( $post->post_type, 'post_type' ) ) {
		return true;
	}

	return false;
}

/**
 * See if the current user has a certain privilege
 *
 * @param mixed  $privs  The privilege name or names (array if multiple)
 * @param string $method The access method ("AND", "OR")
 *
 * @return bool
 * @since 1.2.0
 */
function pods_access( $privs, $method = 'OR' ) {
	// Convert $privs to an array
	$privs = (array) $privs;

	// Convert $method to uppercase
	$method = strtoupper( $method );

	$check = apply_filters( 'pods_access', null, $privs, $method );
	if ( null !== $check && is_bool( $check ) ) {
		return $check;
	}

	if ( ! is_user_logged_in() ) {
		return false;
	}

	if ( pods_is_admin( array( 'pods', 'pods_content' ) ) ) {
		return true;
	}

	// Store approved privs when using "AND"
	$approved_privs = array();

	// Loop through the user's roles
	foreach ( $privs as $priv ) {
		if ( 0 === strpos( $priv, 'pod_' ) ) {
			$priv = pods_str_replace( 'pod_', 'pods_edit_', $priv, 1 );
		}

		if ( 0 === strpos( $priv, 'manage_' ) ) {
			$priv = pods_str_replace( 'manage_', 'pods_', $priv, 1 );
		}

		if ( current_user_can( $priv ) ) {
			if ( 'OR' === $method ) {
				return true;
			}

			$approved_privs[ $priv ] = true;
		}
	}
	if ( 'AND' === strtoupper( $method ) ) {
		foreach ( $privs as $priv ) {
			if ( 0 === strpos( $priv, 'pod_' ) ) {
				$priv = pods_str_replace( 'pod_', 'pods_edit_', $priv, 1 );
			}

			if ( 0 === strpos( $priv, 'manage_' ) ) {
				$priv = pods_str_replace( 'manage_', 'pods_', $priv, 1 );
			}

			if ( ! isset( $approved_privs[ $priv ] ) ) {
				return false;
			}
		}

		return true;
	}

	return false;
}

/**
 * Check whether a Pods shortcode is currently being parsed.
 * If a boolean is passed it overwrites the status.
 *
 * @param bool $bool
 *
 * @return bool
 * @since  2.7.13
 */
function pods_doing_shortcode( $bool = null ) {
	static $check = false;
	if ( null !== $bool ) {
		$check = (bool) $bool;
	}
	return $check;
}

/**
 * Check whether we are currently in a JSON request.
 *
 * @since  2.8.0
 *
 * @return bool Whether we are in a REST API or JSON request.
 */
function pods_doing_json() {
	// Check whether we are doing a REST API request.
	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
		return true;
	}

	// Return whether we are doing a JSON request.
	return wp_is_json_request();
}

/**
 * Shortcode support for use anywhere that support WP Shortcodes.
 * Will return error message on failure.
 *
 * @since 1.6.7
 * @since 2.7.13 Try/Catch.
 *
 * @param array  $tags    An associative array of shortcode properties.
 * @param string $content A string that represents a template override.
 *
 * @return string
 */
function pods_shortcode( $tags, $content = null ) {
	pods_doing_shortcode( true );

	$return_exception = static function() {
		return 'exception';
	};

	add_filter( 'pods_error_mode', $return_exception, 50 );
	add_filter( 'pods_error_exception_fallback_enabled', '__return_false', 50 );

	try {
		$return = pods_shortcode_run( $tags, $content );
	} catch ( Exception $exception ) {
		$return = '';

		if ( pods_is_debug_display() ) {
			$return = pods_message(
				sprintf(
					'<strong>%1$s:</strong> %2$s',
					esc_html__( 'Pods Renderer Error', 'pods' ),
					esc_html( $exception->getMessage() )
				),
				'error',
				true
			);

			$return .= '<pre style="overflow:scroll">' . esc_html( $exception->getTraceAsString() ) . '</pre>';
		} elseif (
			is_user_logged_in()
			&& (
				is_admin()
				|| (
					wp_is_json_request()
					&& did_action( 'rest_api_init' )
				)
			)
		) {
			$return = pods_message(
				sprintf(
					'<strong>%1$s:</strong> %2$s',
					esc_html__( 'Pods Renderer Error', 'pods' ),
				esc_html__( 'There was a problem displaying this content, enable WP_DEBUG in wp-config.php to show more details.', 'pods' )
				),
				'error',
				true
			);
		}
	}

	remove_filter( 'pods_error_mode', $return_exception, 50 );
	remove_filter( 'pods_error_exception_fallback_enabled', '__return_false', 50 );

	pods_doing_shortcode( false );

	return $return;
}

/**
 * Wrap the HTML using attributes for the element.
 *
 * This is used to support Blocks and other elements that use custom attributes like class and anchor.
 *
 * @since 2.8.9
 *
 * @param string $html       The HTML to wrap.
 * @param array  $attributes List of attributes for the element.
 *
 * @return string The wrapped HTML.
 */
function pods_wrap_html( $html, $attributes = [] ) {
	if ( empty( $attributes ) || '' === trim( $html ) ) {
		return $html;
	}

	$container = [];

	// Handle support for className.
	if ( ! empty( $attributes['className'] ) ) {
		$container['class'] = trim( $attributes['className'] );
	}

	// Handle align support.
	if ( ! empty( $attributes['align'] ) ) {
		if ( empty( $container['class'] ) ) {
			$container['class'] = '';
		}

        $container['class'] = trim( 'align' . $attributes['align'] . ' ' . $container['class'] );
    }

	// Handle support for anchor.
	if ( ! empty( $attributes['anchor'] ) ) {
		$container['id'] = $attributes['anchor'];
	}

	if ( empty( $container ) ) {
		return $html;
	}

	ob_start();
	PodsForm::attributes( $container, '_pods_wrap', '_pods_wrap', $attributes );
	$html_attributes = ob_get_clean();

	return sprintf( '<div%1$s>%2$s</div>', $html_attributes, $html );
}

/**
 * Shortcode support for use anywhere that support WP Shortcodes.
 *
 * @since 2.7.13
 *
 * @param array  $tags    An associative array of shortcode properties.
 * @param string $content A string that represents a template override.
 *
 * @return string
 */
function pods_shortcode_run( $tags, $content = null ) {
	if ( defined( 'PODS_DISABLE_SHORTCODE' ) && PODS_DISABLE_SHORTCODE ) {
		return '';
	}

	// For enforcing pagination parameters when not displaying pagination
	$page   = 1;
	$offset = 0;

	if ( isset( $tags['page'] ) ) {
		$page = (int) $tags['page'];
		$page = max( $page, 1 );
	}

	if ( isset( $tags['offset'] ) ) {
		$offset = (int) $tags['offset'];
		$offset = max( $offset, 0 );
	}

	// Query related tags separated to use later.
	$default_query_tags = array(
		'use_current'         => false,
		'name'                => null,
		'id'                  => null,
		'slug'                => null,
		'select'              => null,
		'join'                => null,
		'order'               => null,
		'orderby'             => null,
		'limit'               => null,
		'where'               => null,
		'having'              => null,
		'groupby'             => null,
		'search'              => true,
		'pagination'          => false,
		'page'                => null,
		'offset'              => null,
		'filters_enable'      => null,
		'filters'             => '',
		'filters_label'       => null,
		'filters_location'    => 'before',
		'pagination_label'    => null,
		'pagination_type'     => null,
		'pagination_location' => 'after',
	);

	$default_other_tags = [
		'blog_id'          => null,
		'field'            => null,
		'col'              => null,
		'template'         => null,
		'pods_page'        => null,
		'helper'           => null,
		'form'             => null,
		'form_output_type' => 'div',
		'fields'           => null,
		'label'            => null,
		'thank_you'        => null,
		'not_found'        => null,
		'view'             => null,
		'cache_mode'       => 'none',
		'expires'          => 0,
		'shortcodes'       => false,
		'className'        => null,
		'anchor'           => null,
		'align'            => null,
	];

	$defaults = array_merge( $default_other_tags, $default_query_tags );

	if ( ! empty( $tags ) ) {
		$tags = array_merge( $defaults, $tags );
	} else {
		$tags = $defaults;
	}

	$tags = apply_filters( 'pods_shortcode', $tags );

	$tags['pagination']  = filter_var( $tags['pagination'], FILTER_VALIDATE_BOOLEAN );
	$tags['search']      = filter_var( $tags['search'], FILTER_VALIDATE_BOOLEAN );
	$tags['use_current'] = filter_var( $tags['use_current'], FILTER_VALIDATE_BOOLEAN );

	if ( empty( $content ) ) {
		$content = null;
	}

	// Allow views only if not targeting a file path (must be within theme)
	if ( 0 < strlen( $tags['view'] ) ) {
		$return = '';

		if ( ( ! defined( 'PODS_SHORTCODE_ALLOW_VIEWS' ) || PODS_SHORTCODE_ALLOW_VIEWS ) && ! file_exists( $tags['view'] ) ) {
			$return = pods_view( $tags['view'], null, (int) $tags['expires'], $tags['cache_mode'], true );

			if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
				$return = do_shortcode( $return );
			}

			$return = pods_wrap_html( $return, $tags );
		}

		/**
		 * Allow customization of shortcode output based on shortcode attributes.
		 *
		 * @since 2.7.9
		 *
		 * @param string    $return  Shortcode output to return.
		 * @param array     $tags    Shortcode attributes.
		 * @param null|Pods $pod     Pods object, or null if 'view' context.
		 * @param string    $context The shortcode context (form, field, pods-page, view, or list).
		 */
		return apply_filters( 'pods_shortcode_output', $return, $tags, null, 'view' );
	}

	$blog_is_switched = false;

	if ( defined( 'PODS_SHORTCODE_ALLOW_BLOG_SWITCHING' ) && PODS_SHORTCODE_ALLOW_BLOG_SWITCHING && is_multisite() ) {
		if ( ! empty( $tags['blog_id'] ) && is_numeric( $tags['blog_id'] ) && (int) get_current_blog_id() !== (int) $tags['blog_id'] ) {
			switch_to_blog( (int) $tags['blog_id'] );

			$blog_is_switched = true;
		}
	}

	if ( ! $tags['use_current'] && empty( $tags['name'] ) ) {
		$has_query_tags = array_intersect_key( array_diff( $tags, $defaults ), $default_query_tags );

		// Only allow revert to current object if there are no query tags.
		if ( ! $has_query_tags ) {
			/**
			 * Allow filtering whether to detect the pod name / item ID from the current post object.
			 *
			 * @since 2.7.26
			 *
			 * @param bool  $detect_from_current  Whether to detect the pod name / item ID from the current post object.
			 * @param array $shortcode_attributes The list of attributes used for the shortcode.
			 */
			$detect_from_current = apply_filters( 'pods_shortcode_detect_from_current_post', in_the_loop(), $tags );

			// Archives, Post type archives, singular posts.
			if ( $detect_from_current ) {
				$pod = pods( get_post_type(), get_the_ID(), false );

				if ( ! empty( $pod ) ) {
					$id           = get_the_ID();
					$tags['id']   = $id;
					$tags['name'] = get_post_type();
				}
			} else {
				$tags['use_current'] = true;
			}
		}

		if ( ! $tags['use_current'] && empty( $tags['name'] ) ) {
			if ( $blog_is_switched ) {
				restore_current_blog();
			}

			return '<p>' . esc_html__( 'Pods embed error: Please provide a Pod name', 'pods' ) . '</p>';
		}
	}

	if ( ! empty( $tags['col'] ) ) {
		$tags['field'] = $tags['col'];

		unset( $tags['col'] );
	}

	if ( ! empty( $tags['order'] ) ) {
		$tags['orderby'] = $tags['order'];

		unset( $tags['order'] );
	}

	if ( empty( $content ) && empty( $tags['pods_page'] ) && empty( $tags['template'] ) && empty( $tags['field'] ) && empty( $tags['form'] ) ) {
		if ( $blog_is_switched ) {
			restore_current_blog();
		}

		return '<p>' . esc_html__( 'Pods embed error: Please provide either a template or field name', 'pods' ) . '</p>';
	}

	if ( ! $tags['use_current'] && ! isset( $id ) ) {
		// id > slug (if both exist)
		$id = null;

		$evaluate_tags_args = array(
			'sanitize'        => true,
			'fallback'        => null,
			'use_current_pod' => true,
		);

		if ( ! empty( $tags['slug'] ) ) {
			$id = $tags['slug'];

			if ( pods_shortcode_allow_evaluate_tags() ) {
				$id = pods_evaluate_tags( $id, $evaluate_tags_args );
			}
		}

		if ( ! empty( $tags['id'] ) ) {
			$id = $tags['id'];

			if ( pods_shortcode_allow_evaluate_tags() ) {
				$id = pods_evaluate_tags( $id, $evaluate_tags_args );
			}

			if ( is_numeric( $id ) ) {
				$id = absint( $id );
			}
		}
	}//end if

	if ( ! isset( $pod ) ) {
		if ( ! $tags['use_current'] ) {
			$pod = pods( $tags['name'], $id );
		} else {
			$pod = pods();
			$id  = $pod->id();
		}
	}

	if ( empty( $pod ) || ! $pod->valid() ) {
		if ( $blog_is_switched ) {
			restore_current_blog();
		}

		return '<p>' . esc_html__( 'Pods embed error: Pod not found', 'pods' ) . '</p>';
	}

	$found = 0;
	$filters = false;

	$is_singular = ( ! empty( $id ) || $tags['use_current'] );

	if ( ! $is_singular ) {
		$params = array();

		if ( ! defined( 'PODS_DISABLE_SHORTCODE_SQL' ) || ! PODS_DISABLE_SHORTCODE_SQL ) {
			$evaluate_tags_args = array(
				'sanitize'        => true,
				'fallback'        => '""',
				'use_current_pod' => true,
			);

			if ( 0 < strlen( $tags['orderby'] ) ) {
				$params['orderby'] = $tags['orderby'];
			}

			if ( 0 < strlen( $tags['where'] ) ) {
				$params['where'] = $tags['where'];

				if ( pods_shortcode_allow_evaluate_tags() ) {
					$params['where'] = pods_evaluate_tags_sql( html_entity_decode( $params['where'] ), $evaluate_tags_args );
				}
			}

			if ( 0 < strlen( $tags['having'] ) ) {
				$params['having'] = $tags['having'];

				if ( pods_shortcode_allow_evaluate_tags() ) {
					$params['having'] = pods_evaluate_tags_sql( html_entity_decode( $params['having'] ), $evaluate_tags_args );
				}
			}

			if ( 0 < strlen( $tags['groupby'] ) ) {
				$params['groupby'] = $tags['groupby'];
			}

			if ( 0 < strlen( $tags['select'] ) ) {
				$params['select'] = $tags['select'];
			}
			if ( 0 < strlen( $tags['join'] ) ) {
				$params['join'] = $tags['join'];
			}
		}//end if

		// Load filters and return HTML for later use.
		if (
			true === (bool) $tags['filters_enable']
			|| (
				! empty( $tags['filters'] )
				&& null === $tags['filters_enable']
			)
		) {
			$filters_params = [
				'fields' => (string) $tags['filters'],
				'label'  => (string) $tags['filters_label'],
			];

			$filters = $pod->filters( $filters_params );
		}

		// Forms require params set
		if ( ! empty( $params ) || empty( $tags['form'] ) ) {
			if ( ! empty( $tags['limit'] ) ) {
				$params['limit'] = (int) $tags['limit'];
			}

			$params['search'] = $tags['search'];

			$params['pagination'] = $tags['pagination'];

			// If we aren't displaying pagination, we need to enforce page/offset
			if ( ! $params['pagination'] ) {
				$params['page']   = $page;
				$params['offset'] = $offset;

				// Force pagination on, we need it and we're enforcing page/offset
				$params['pagination'] = true;
			} else {
				// If we are displaying pagination, allow page/offset override only if *set*
				if ( isset( $tags['page'] ) ) {
					$params['page'] = (int) $tags['page'];
					$params['page'] = max( $params['page'], 1 );
				}

				if ( isset( $tags['offset'] ) ) {
					$params['offset'] = (int) $tags['offset'];
					$params['offset'] = max( $params['offset'], 0 );
				}
			}

			if ( ! empty( $tags['cache_mode'] ) && 'none' !== $tags['cache_mode'] ) {
				$params['cache_mode'] = $tags['cache_mode'];
				$params['expires']    = (int) $tags['expires'];
			}

			$params = apply_filters( 'pods_shortcode_findrecords_params', $params, $pod, $tags );

			$pod->find( $params );

			$found = $pod->total_found();
		}//end if
	}//end if

	// Handle form output.
	if ( ! empty( $tags['form'] ) ) {
		if ( 'user' === $pod->pod ) {
			if ( false !== strpos( $tags['fields'], '_capabilities' ) || false !== strpos( $tags['fields'], '_user_level' ) ) {
				if ( $blog_is_switched ) {
					restore_current_blog();
				}

				// Further hardening of User-based forms
				return '';
			} elseif ( $is_singular && ( ! defined( 'PODS_SHORTCODE_ALLOW_USER_EDIT' ) || ! PODS_SHORTCODE_ALLOW_USER_EDIT ) ) {
				if ( $blog_is_switched ) {
					restore_current_blog();
				}

				// Only explicitly allow user edit forms
				return '';
			}
		}

		$form_params = [
			'fields'      => $tags['fields'],
			'label'       => $tags['label'],
			'thank_you'   => $tags['thank_you'],
			'output_type' => ! empty( $tags['form_output_type'] ) ? $tags['form_output_type'] : 'div',
		];

		$return = $pod->form( $form_params );

		$return = pods_wrap_html( $return, $tags );

		if ( $blog_is_switched ) {
			restore_current_blog();
		}

		/**
		 * Allow customization of shortcode output based on shortcode attributes.
		 *
		 * @since 2.7.9
		 *
		 * @param string    $return  Shortcode output to return.
		 * @param array     $tags    Shortcode attributes.
		 * @param null|Pods $pod     Pods object, or null if 'view' context.
		 * @param string    $context The shortcode context (form, field, pods-page, view, or list).
		 */
		return apply_filters( 'pods_shortcode_output', $return, $tags, $pod, 'form' );
	}

	// Handle field output.
	if ( ! empty( $tags['field'] ) ) {
		if ( $tags['template'] || $content ) {
			$return  = '';
			$related = $pod->field( $tags['field'], array( 'output' => 'find' ) );

			if ( $related instanceof Pods && $related->valid() ) {
				// Content is null by default.
				$return .= $related->template( $tags['template'], $content );
			}
		} elseif ( empty( $tags['helper'] ) ) {
			$return = $pod->display( $tags['field'] );
		} else {
			$return = $pod->helper( $tags['helper'], $pod->field( $tags['field'] ), $tags['field'] );
		}

		// @todo $blog_is_switched >> Switch back before running other shortcodes?
		if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
			$return = do_shortcode( $return );
		}

		$return = pods_wrap_html( $return, $tags );

		if ( $blog_is_switched ) {
			restore_current_blog();
		}

		/**
		 * Allow customization of shortcode output based on shortcode attributes.
		 *
		 * @since 2.7.9
		 *
		 * @param string    $return  Shortcode output to return.
		 * @param array     $tags    Shortcode attributes.
		 * @param null|Pods $pod     Pods object, or null if 'view' context.
		 * @param string    $context The shortcode context (form, field, pods-page, view, or list).
		 */
		return apply_filters( 'pods_shortcode_output', $return, $tags, $pod, 'field' );
	}

	// Handle Pods Page output.
	if ( ! empty( $tags['pods_page'] ) && class_exists( 'Pods_Pages' ) ) {
		$pods_page = Pods_Pages::exists( $tags['pods_page'] );

		if ( empty( $pods_page ) ) {
			if ( $blog_is_switched ) {
				restore_current_blog();
			}

			return '<p>' . esc_html__( 'Pods embed error: Pods Page not found.', 'pods' ) . '</p>';
		}

		$return = Pods_Pages::content( true, $pods_page );

		// @todo $blog_is_switched >> Switch back before running other shortcodes?
		if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
			$return = do_shortcode( $return );
		}

		$return = pods_wrap_html( $return, $tags );

		if ( $blog_is_switched ) {
			restore_current_blog();
		}

		/**
		 * Allow customization of shortcode output based on shortcode attributes.
		 *
		 * @since 2.7.9
		 *
		 * @param string    $return  Shortcode output to return.
		 * @param array     $tags    Shortcode attributes.
		 * @param null|Pods $pod     Pods object, or null if 'view' context.
		 * @param string    $context The shortcode context (form, field, pods-page, view, or list).
		 */
		return apply_filters( 'pods_shortcode_output', $return, $tags, $pod, 'pods-page' );
	}//end if

	$pagination = false;

	// Only handle pagination on non-singular shortcodes where items were found.
	if (
		! $is_singular
		&& 0 < $found
		&& (
			empty( $params['limit'] )
			|| (
				0 < $params['limit']
				&& $params['limit'] < $found
			)
		)
		&& true === $tags['pagination']
	) {
		$pagination_params = array(
			'label' => pods_v( 'pagination_label', $tags, null ),
			'type'  => pods_v( 'pagination_type', $tags, null ),
		);

		// Remove empty params.
		$pagination_params = array_filter( $pagination_params );

		$pagination = $pod->pagination( $pagination_params );
	}

	ob_start();

	if ( $filters && 'before' === $tags['filters_location'] ) {
		// phpcs:ignore
		echo $filters;
	}

	if ( $pagination && in_array( $tags['pagination_location'], [ 'before', 'both' ], true ) ) {
		// phpcs:ignore
		echo $pagination;
	}

	$content = $pod->template( $tags['template'], $content );

	if ( '' === trim( $content ) && ! empty( $tags['not_found'] ) ) {
		$content = $pod->do_magic_tags( $tags['not_found'] );
	}

	// phpcs:ignore
	echo $content;

	if ( $pagination && in_array( $tags['pagination_location'], [ 'after', 'both' ], true ) ) {
		// phpcs:ignore
		echo $pagination;
	}

	if ( $filters && 'after' === $tags['filters_location'] ) {
		// phpcs:ignore
		echo $filters;
	}

	$return = ob_get_clean();

	if ( $tags['shortcodes'] && defined( 'PODS_SHORTCODE_ALLOW_SUB_SHORTCODES' ) && PODS_SHORTCODE_ALLOW_SUB_SHORTCODES ) {
		$return = do_shortcode( $return );
	}

	$return = pods_wrap_html( $return, $tags );

	if ( $blog_is_switched ) {
		restore_current_blog();
	}

	/**
	 * Allow customization of shortcode output based on shortcode attributes.
	 *
	 * @since 2.7.9
	 *
	 * @param string    $return  Shortcode output to return.
	 * @param array     $tags    Shortcode attributes.
	 * @param null|Pods $pod     Pods object, or null if 'view' context.
	 * @param string    $context The shortcode context (form, field, pods-page, view, or list).
	 */
	return apply_filters( 'pods_shortcode_output', $return, $tags, $pod, 'list' );
}

/**
 * Form Shortcode support for use anywhere that support WP Shortcodes.
 *
 * @param array  $tags    An associative array of shortcode properties.
 * @param string $content Not currently used.
 *
 * @return string
 * @since 2.3.0
 */
function pods_shortcode_form( $tags, $content = null ) {
	$tags['form'] = 1;

	return pods_shortcode( $tags, $content );
}

/**
 * Fork of WordPress do_shortcode that allows specifying which shortcodes are ran.
 *
 * Search content for shortcodes and filter shortcodes through their hooks.
 *
 * If there are no shortcode tags defined, then the content will be returned
 * without any filtering. This might cause issues when plugins are disabled but
 * the shortcode will still show up in the post or content.
 *
 * @since 2.4.3
 *
 * @uses  $shortcode_tags
 * @uses  get_shortcode_regex() Gets the search pattern for searching shortcodes.
 *
 * @param string $content            Content to search for shortcodes.
 * @param array  $shortcodes         Array of shortcodes to run.
 * @param array  $ignored_shortcodes Array of shortcodes to ignore.
 *
 * @return string Content with shortcodes filtered out.
 */
function pods_do_shortcode( $content, $shortcodes = [], $ignored_shortcodes = [] ) {
	global $shortcode_tags;

	// No shortcodes in content
	if ( false === strpos( $content, '[' ) ) {
		return $content;
	}

	// No shortcodes registered
	if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
		return $content;
	}

	$only_shortcodes   = ! empty( $shortcodes );
	$ignore_shortcodes = ! empty( $ignored_shortcodes );

	if ( $only_shortcodes || $ignore_shortcodes ) {
		$temp_shortcode_filter = static function ( $return, $tag, $attr, $m ) use ( $only_shortcodes, $shortcodes, $ignore_shortcodes, $ignored_shortcodes ) {
			if ( $only_shortcodes && in_array( $m[2], $shortcodes, true ) ) {
				// If shortcode being called is in list, return false to allow it to run.
				return false;
			}

			if ( $ignore_shortcodes && ! in_array( $m[2], $ignored_shortcodes, true ) ) {
				// If shortcode being called is not in ignore list, return false to allow it to run.
				return false;
			}

			// Return original shortcode string if we aren't going to handle at this time
			return $m[0];
		};

		add_filter( 'pre_do_shortcode_tag', $temp_shortcode_filter, 10, 4 );
	}

	// Build Shortcode regex pattern just for the shortcodes we want
	$pattern = get_shortcode_regex();

	// Call shortcode callbacks just for the shortcodes we want
	$content = preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );

	if ( isset( $temp_shortcode_filter ) ) {
		remove_filter( 'pre_do_shortcode_tag', $temp_shortcode_filter );
	}

	return $content;
}

/**
 * Check if Pods is compatible with WP / PHP / MySQL or not
 *
 * @return bool
 *
 * @since 1.10
 */
function pods_compatibility_check() {
	$compatible = true;

	if ( ! pods_version_check( 'wp', PODS_WP_VERSION_MINIMUM ) ) {
		$compatible = false;

		add_action( 'admin_notices', 'pods_version_notice_wp' );
	}

	if ( ! pods_version_check( 'php', PODS_PHP_VERSION_MINIMUM ) ) {
		$compatible = false;

		add_action( 'admin_notices', 'pods_version_notice_php' );
	}

	if ( ! pods_version_check( 'mysql', PODS_MYSQL_VERSION_MINIMUM ) ) {
		$compatible = false;

		add_action( 'admin_notices', 'pods_version_notice_mysql' );
	}

	return $compatible;
}

/**
 * Show WP notice if WP version is incompatible
 *
 * @return void
 *
 * @since 1.10
 */
function pods_version_notice_wp() {
	global $wp_version;
	?>
	<div class="error fade">
		<p>
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
			<strong>WordPress <?php echo esc_html( PODS_WP_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
			<strong>WordPress <?php echo esc_html( $wp_version ); ?></strong> - <?php _e( 'Please upgrade your WordPress to continue.', 'pods' ); ?>
		</p>
	</div>
	<?php
}

/**
 * Show WP notice if PHP version is incompatible
 *
 * @return void
 *
 * @since 1.10
 */
function pods_version_notice_php() {
	?>
	<div class="error fade">
		<p>
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
			<strong>PHP <?php echo esc_html( PODS_PHP_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
			<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' ); ?>
		</p>
	</div>
	<?php
}

/**
 * Show WP notice if MySQL version is incompatible
 *
 * @return void
 *
 * @since 1.10
 */
function pods_version_notice_mysql() {
	global $wpdb;
	$mysql = $wpdb->db_version();
	?>
	<div class="error fade">
		<p>
			<strong><?php _e( 'NOTICE', 'pods' ); ?>:</strong> Pods <?php echo esc_html( PODS_VERSION ); ?> <?php _e( 'requires a minimum of', 'pods' ); ?>
			<strong>MySQL <?php echo esc_html( PODS_MYSQL_VERSION_MINIMUM ); ?>+</strong> <?php _e( 'to function. You are currently running', 'pods' ); ?>
			<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' ); ?>
		</p>
	</div>
	<?php
}

/**
 * Check if a Function exists or File exists in Theme / Child Theme
 *
 * @param string $function_or_file Function or file name to look for.
 * @param string $function_name    (optional) Function name to look for.
 * @param string $file_dir         (optional) Drectory to look into
 * @param string $file_name        (optional) Filename to look for
 *
 * @return mixed
 *
 * @since 1.12
 */
function pods_function_or_file( $function_or_file, $function_name = null, $file_dir = null, $file_name = null ) {
	$found            = false;
	$function_or_file = (string) $function_or_file;
	if ( false !== $function_name ) {
		if ( null === $function_name ) {
			$function_name = $function_or_file;
		}
		$function_name = str_replace( array(
			'__',
			'__',
			'__',
		), '_', preg_replace( '/[^a-z^A-Z^_][^a-z^A-Z^0-9^_]*/', '_', (string) $function_name ) );
		if ( function_exists( 'pods_custom_' . $function_name ) ) {
			$found = array( 'function' => 'pods_custom_' . $function_name );
		} elseif ( function_exists( $function_name ) ) {
			$found = array( 'function' => $function_name );
		}
	}
	if ( false !== $file_name && false === $found ) {
		if ( null === $file_name ) {
			$file_name = $function_or_file;
		}
		$file_name       = str_replace( array(
				'__',
				'__',
				'__',
			), '_', preg_replace( '/[^a-z^A-Z^0-9^_]*/', '_', (string) $file_name ) ) . '.php';
		$custom_location = apply_filters( 'pods_file_directory', null, $function_or_file, $function_name, $file_dir, $file_name );
		if ( defined( 'PODS_FILE_DIRECTORY' ) && false !== PODS_FILE_DIRECTORY ) {
			$custom_location = PODS_FILE_DIRECTORY;
		}
		if ( ! empty( $custom_location ) && locate_template( trim( $custom_location, '/' ) . '/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name ) ) {
			$found = array( 'file' => trim( $custom_location, '/' ) . '/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name );
		} elseif ( locate_template( 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name ) ) {
			$found = array( 'file' => 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '/' : '' ) . $file_name );
		} elseif ( locate_template( 'pods-' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name ) ) {
			$found = array( 'file' => 'pods-' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name );
		} elseif ( locate_template( 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name ) ) {
			$found = array( 'file' => 'pods/' . ( ! empty( $file_dir ) ? $file_dir . '-' : '' ) . $file_name );
		}
	}//end if

	return apply_filters( 'pods_function_or_file', $found, $function_or_file, $function_name, $file_name );
}

/**
 * Redirects to another page.
 *
 * @param string  $location The path to redirect to
 * @param int     $status   Status code to use
 * @param boolean $die      If true, PHP code exection will stop
 *
 * @return void
 *
 * @since 2.0.0
 */
function pods_redirect( $location, $status = 302, $die = true ) {
	if ( ! headers_sent() ) {
		wp_redirect( $location, $status );
		if ( $die ) {
			die();
		}
	} else {
		echo '<script type="text/javascript">' . 'document.location = "' . str_replace( '&amp;', '&', esc_js( $location ) ) . '";' . '</script>';
		if ( $die ) {
			die();
		}
	}
}

/**
 * Check if a user has permission to be doing something based on standard permission options
 *
 * @param array|Whatsit $object The object data.
 *
 * @return bool Whether the user has permissions.
 *
 * @since 2.0.5
 */
function pods_permission( $object ) {
	$permissions = pods_container( Permissions::class );

	return $permissions->user_has_permission( $object );
}

/**
 * Check if permissions are restricted for an object.
 *
 * @since 2.3.4
 *
 * @param array|Whatsit $object The object data.
 *
 * @return bool Whether the permissions are restricted for an object.
 */
function pods_has_permissions( $object ) {
	$permissions = pods_container( Permissions::class );

	return $permissions->are_permissions_restricted( $object );
}

/**
 * A fork of get_page_by_title that excludes items unavailable via access rights (by status)
 *
 * @see   get_page_by_title
 *
 * @param string       $title   Title of item to get
 * @param string       $output  Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
 * @param string       $type    Post Type
 * @param string|array $status  Post statuses to include (default is what user has access to)
 * @param bool         $return  Whether to return the 'id' or 'post'.
 *
 * @return WP_Post|null WP_Post on success or null on failure
 *
 * @since 2.3.4
 */
function pods_by_title( $title, $output = OBJECT, $type = 'page', $status = null, $return = 'post' ) {
	// @todo support Pod item lookups, not just Post Types
	/**
	 * @var $wpdb WPDB
	 */
	global $wpdb;

	if ( empty( $status ) ) {
		$status = array(
			'publish',
		);

		if ( current_user_can( 'read_private_' . $type . 's' ) ) {
			$status[] = 'private';
		}

		if ( current_user_can( 'edit_' . $type . 's' ) ) {
			$status[] = 'draft';
		}
	}

	$status = (array) $status;

	$status_sql = ' AND `post_status` IN ( %s' . str_repeat( ', %s', count( $status ) - 1 ) . ' )';

	$orderby_sql = ' ORDER BY ( `post_status` = %s ) DESC' . str_repeat( ', ( `post_status` = %s ) DESC', count( $status ) - 1 ) . ', `ID` DESC';

	// Once for WHERE, once for ORDER BY
	$prepared = array_merge( array( $title, $type ), $status, $status );

	$page = (int) $wpdb->get_var( $wpdb->prepare( "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_title` = %s AND `post_type` = %s" . $status_sql . $orderby_sql, $prepared ) );

	if ( 0 < $page ) {
		if ( 'id' === $return ) {
			return $page;
		}

		return get_post( $page, $output );
	}

	return null;
}

/**
 * Get a field value from a Pod.
 *
 * @param string|null  $pod    The pod name, or if you are in The Loop then you can just provide the field name to auto-detect pod/id using loop information.
 * @param mixed|null   $id     The ID or slug of the item.
 * @param string|array $name   The field name, or an associative array of parameters.
 * @param boolean      $single For tableless fields, to return the whole array or the just the first item.
 *
 * @return mixed Field value.
 *
 * @since 2.1.0
 */
function pods_field( $pod, $id = null, $name = null, $single = false ) {
	// allow for pods_field( 'field_name' );
	if ( null === $name ) {
		$name   = $pod;
		$single = (boolean) $id;

		$pod = null;
		$id  = null;
	}

	if ( null === $pod && null === $id ) {
		$pod = get_post_type();
		$id  = get_the_ID();
	}

	$pod_object = pods( $pod, $id );

	if ( is_object( $pod_object ) && $pod_object->exists() ) {
		return $pod_object->field( $name, $single );
	}

	return null;
}

/**
 * Get the data field value.
 *
 * @since 2.9.4
 *
 * @param Pods|string|null $obj        The pod name or Pods object.
 * @param string           $field_name The field name.
 *
 * @return mixed The data field value.
 */
function pods_data_field( $obj, $field_name ) {
	if ( is_string( $obj ) ) {
		$obj = pods( $obj );
	}

	$traverse_fields = explode( '.', $field_name );
	$is_traversal    = 1 < count( $traverse_fields );
	$first_field     = $traverse_fields[0];

	// Get the first field name data.
	$field_data = $obj ? $obj->fields( $first_field ) : null;

	// Ensure the field name is using the correct name and not the alias.
	if ( $field_data ) {
		$first_field = $field_data['name'];

		if ( ! $is_traversal ) {
			$field_name = $first_field;
		}
	}

	if ( $obj && ! $field_data && ! $is_traversal ) {
		// Get the full field name data.
		$field_data = $obj->fields( $field_name );
	}

	$is_field_set = false;

	if ( $field_data instanceof Object_Field ) {
		$is_field_set = true;
	} elseif ( $field_data instanceof Field ) {
		$is_field_set = true;
	}

	// Handle custom/supported value mappings.
	$map_field_values = pods_container( Map_Field_Values::class );

	return $map_field_values->map_value( $first_field, $traverse_fields, $is_field_set ? $field_data : null, $obj );
}

/**
 * Get a field display value from a Pod.
 *
 * @param string|null  $pod    The pod name, or if you are in The Loop then you can just provide the field name to auto-detect pod/id using loop information.
 * @param mixed|null   $id     The ID or slug of the item.
 * @param string|array $name   The field name, or an associative array of parameters.
 * @param boolean      $single For tableless fields, to return the whole array or the just the first item.
 *
 * @return mixed Field value.
 *
 * @since 2.1.0
 */
function pods_field_display( $pod, $id = null, $name = null, $single = false ) {
	// allow for pods_field_display( 'field_name' );
	if ( null === $name ) {
		$name   = $pod;
		$single = (boolean) $id;

		$pod = null;
		$id  = null;
	}

	if ( null === $pod && null === $id ) {
		$pod = get_post_type();
		$id  = get_the_ID();
	}

	$pod_object = pods( $pod, $id );

	if ( is_object( $pod_object ) && $pod_object->exists() ) {
		return $pod_object->display( $name, $single );
	}

	return null;
}

/**
 * Get a field raw value from a Pod.
 *
 * @param string|null  $pod    The pod name.
 * @param mixed|null   $id     The ID or slug of the item.
 * @param string|array $name   The field name, or an associative array of parameters.
 * @param boolean      $single For tableless fields, to return the whole array or the just the first item.
 *
 * @return mixed Field value.
 *
 * @since 2.1.0
 */
function pods_field_raw( $pod, $id = null, $name = null, $single = false ) {
	// allow for pods_field_raw( 'field_name' );
	if ( null === $name ) {
		$name   = $pod;
		$single = (boolean) $id;

		$pod = null;
		$id  = null;
	}

	if ( null === $pod && null === $id ) {
		$pod = get_post_type();
		$id  = get_the_ID();
	}

	$pod_object = pods( $pod, $id );

	if ( is_object( $pod_object ) && $pod_object->exists() ) {
		return $pod_object->raw( $name, $single );
	}

	return null;

}

/**
 * Update a field value for a Pod.
 *
 * @param string|null  $pod   The pod name.
 * @param mixed|null   $id    The ID or slug of the item.
 * @param string|array $name  The field name, or an associative array of parameters.
 * @param boolean      $value Value to save.
 *
 * @return int|false The item ID or false if not saved.
 *
 * @since 2.7.17
 */
function pods_field_update( $pod, $id = null, $name = null, $value = null ) {

	// allow for pods_field( 'field_name' );
	if ( null === $name ) {
		$name  = $pod;
		$value = $id;

		$pod = null;
		$id  = null;
	}

	if ( null === $pod && null === $id ) {
		$pod = get_post_type();
		$id  = get_the_ID();
	}

	$pod_object = pods( $pod, $id );

	if ( is_object( $pod_object ) && $pod_object->exists() ) {
		return $pod_object->save( $name, $value );
	}

	return false;
}

/**
 * Set a cached value
 *
 * @see   PodsView::set
 *
 * @param string $key        Key for the cache
 * @param mixed  $value      Value to add to the cache
 * @param int    $expires    (optional) Time in seconds for the cache to expire, if 0 no expiration.
 * @param string $cache_mode (optional) Decides the caching method to use for the view.
 * @param string $group      (optional) Key for the group
 *
 * @return bool|mixed|null|string|void
 *
 * @since 2.0.0
 */
function pods_view_set( $key, $value, $expires = 0, $cache_mode = 'cache', $group = '' ) {
	return PodsView::set( $key, $value, $expires, $cache_mode, $group );
}

/**
 * Get a cached value
 *
 * @see   PodsView::get
 *
 * @param string $key        Key for the cache
 * @param string $cache_mode (optional) Decides the caching method to use for the view.
 * @param string $group      (optional) Key for the group
 * @param string $callback   (optional) Callback function to run to set the value if not cached
 *
 * @return bool|mixed|null|void
 *
 * @since 2.0.0
 */
function pods_view_get( $key, $cache_mode = 'cache', $group = '', $callback = null ) {
	return PodsView::get( $key, $cache_mode, $group, $callback );
}

/**
 * Clear a cached value
 *
 * @see   PodsView::clear
 *
 * @param string|bool $key        Key for the cache
 * @param string      $cache_mode (optional) Decides the caching method to use for the view.
 * @param string      $group      (optional) Key for the group
 *
 * @return bool
 *
 * @since 2.0.0
 */
function pods_view_clear( $key = true, $cache_mode = 'cache', $group = '' ) {
	return PodsView::clear( $key, $cache_mode, $group );
}

/**
 * Set a cached value
 *
 * @see   PodsView::set
 *
 * @param string $key     Key for the cache
 * @param mixed  $value   Value to add to the cache
 * @param string $group   (optional) Key for the group
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
 *
 * @return bool|mixed|null|string|void
 *
 * @since 2.0.0
 */
function pods_cache_set( $key, $value, $group = '', $expires = 0 ) {
	return pods_view_set( $key, $value, $expires, 'cache', $group );
}

/**
 * Get a cached value
 *
 * @see   PodsView::get
 *
 * @param string $key      Key for the cache
 * @param string $group    (optional) Key for the group
 * @param string $callback (optional) Callback function to run to set the value if not cached
 *
 * @return bool
 *
 * @since 2.0.0
 */
function pods_cache_get( $key, $group = '', $callback = null ) {
	return pods_view_get( $key, 'cache', $group, $callback );
}

/**
 * Clear a cached value
 *
 * @see   PodsView::clear
 *
 * @param string|bool $key   Key for the cache
 * @param string      $group (optional) Key for the group
 *
 * @return bool|mixed|null|void
 *
 * @since 2.0.0
 */
function pods_cache_clear( $key = true, $group = '' ) {
	return pods_view_clear( $key, 'cache', $group );
}

/**
 * Set a cached value
 *
 * @see   PodsView::set
 *
 * @param string $key     Key for the cache
 * @param mixed  $value   Value to add to the cache
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
 *
 * @return bool|mixed|null|string|void
 *
 * @since 2.0.0
 */
function pods_transient_set( $key, $value, $expires = 0 ) {
	return pods_view_set( $key, $value, $expires, 'transient' );
}

/**
 * Get a cached value
 *
 * @see   PodsView::get
 *
 * @param string $key      Key for the cache
 * @param string $callback (optional) Callback function to run to set the value if not cached
 *
 * @return bool|mixed|null|void
 *
 * @since 2.0.0
 */
function pods_transient_get( $key, $callback = null ) {
	return pods_view_get( $key, 'transient', '', $callback );
}

/**
 * Clear a cached value
 *
 * @see   PodsView::clear
 *
 * @param string|bool $key Key for the cache
 *
 * @return bool
 *
 * @since 2.0.0
 */
function pods_transient_clear( $key = true ) {
	return pods_view_clear( $key, 'transient' );
}

/**
 * Set a cached value
 *
 * @see   PodsView::set
 *
 * @param string $key     Key for the cache
 * @param mixed  $value   Value to add to the cache
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
 *
 * @return bool|mixed|null|string|void
 *
 * @since 2.3.10
 */
function pods_site_transient_set( $key, $value, $expires = 0 ) {
	return pods_view_set( $key, $value, $expires, 'site-transient' );
}

/**
 * Get a cached value
 *
 * @see   PodsView::get
 *
 * @param string $key      Key for the cache
 * @param string $callback (optional) Callback function to run to set the value if not cached
 *
 * @return bool|mixed|null|void
 *
 * @since 2.3.10
 */
function pods_site_transient_get( $key, $callback = null ) {
	return pods_view_get( $key, 'site-transient', '', $callback );
}

/**
 * Clear a cached value
 *
 * @see   PodsView::clear
 *
 * @param string|bool $key Key for the cache
 *
 * @return bool
 *
 * @since 2.3.10
 */
function pods_site_transient_clear( $key = true ) {
	return pods_view_clear( $key, 'site-transient' );
}

/**
 * Set a cached value
 *
 * @see   PodsView::set
 *
 * @param string $key     Key for the cache
 * @param mixed  $value   Value to add to the cache
 * @param int    $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
 * @param string $group   (optional) Key for the group
 *
 * @return bool|mixed|null|string|void
 *
 * @since 2.3.10
 */
function pods_option_cache_set( $key, $value, $expires = 0, $group = '' ) {
	return pods_view_set( $key, $value, $expires, 'option-cache', $group );
}

/**
 * Get a cached value
 *
 * @see   PodsView::get
 *
 * @param string $key      Key for the cache
 * @param string $group    (optional) Key for the group
 * @param string $callback (optional) Callback function to run to set the value if not cached
 *
 * @return bool|mixed|null|void
 *
 * @since 2.3.10
 */
function pods_option_cache_get( $key, $group = '', $callback = null ) {
	return pods_view_get( $key, 'option-cache', $group, $callback );
}

/**
 * Clear a cached value
 *
 * @see   PodsView::clear
 *
 * @param string|bool $key   Key for the cache
 * @param string      $group (optional) Key for the group
 *
 * @return bool
 *
 * @since 2.3.10
 */
function pods_option_cache_clear( $key = true, $group = '' ) {
	return pods_view_clear( $key, 'option-cache', $group );
}

/**
 * Set a cached value in the Pods Static Cache.
 *
 * @see   PodsView::set
 *
 * @param string $key   Key for the cache.
 * @param mixed  $value Value to add to the cache.
 * @param string $group (optional) Key for the group.
 *
 * @return bool|mixed|null|string|void
 *
 * @since 2.8.18
 */
function pods_static_cache_set( $key, $value, $group = '' ) {
	return pods_view_set( $key, $value, 0, 'static-cache', $group );
}

/**
 * Get a cached value in the Pods Static Cache.
 *
 * @see   PodsView::get
 *
 * @param string $key      Key for the cache.
 * @param string $group    (optional) Key for the group.
 * @param string $callback (optional) Callback function to run to set the value if not cached.
 *
 * @return bool
 *
 * @since 2.8.18
 */
function pods_static_cache_get( $key, $group = '', $callback = null ) {
	return pods_view_get( $key, 'static-cache', $group, $callback );
}

/**
 * Clear a cached value in the Pods Static Cache.
 *
 * @see PodsView::clear
 *
 * @param string|bool $key   Key for the cache.
 * @param string      $group (optional) Key for the group.
 *
 * @return bool|mixed|null|void
 *
 * @since 2.8.18
 */
function pods_static_cache_clear( $key = true, $group = '' ) {
	return pods_view_clear( $key, 'static-cache', $group );
}

/**
 * Scope variables and include a template like get_template_part that's child-theme aware
 *
 * @see   get_template_part
 *
 * @param string|array $template Template names (see get_template_part)
 * @param array        $data     Data to scope to the include
 * @param bool         $return   Whether to return the output (echo by default)
 *
 * @return string|null Template output
 *
 * @since 2.3.9
 */
function pods_template_part( $template, $data = null, $return = false ) {
	$part = PodsView::get_template_part( $template, $data );

	if ( ! $return ) {
		echo $part;

		return null;
	}

	return $part;
}

/**
 * Add a new Pod outside of the DB.
 *
 * @param string $type   The pod type ('post_type', 'taxonomy', 'media', 'user', 'comment')
 * @param string $name   The pod name
 * @return array|boolean|WP_Error Field data or WP_Error if unsuccessful.
 *
 * @return array|boolean Pod data or false if unsuccessful
 * @since 2.1.0
 */
function pods_register_type( $type, $name, $object = null ) {
	if ( empty( $object ) ) {
		$object = [];
	}

	if ( ! empty( $name ) ) {
		$object['name'] = $name;
	}

	if ( ! empty( $type ) ) {
		$object['type'] = $type;
	}

	if ( ! isset( PodsMeta::$queue[ $object['type'] ] ) ) {
		PodsMeta::$queue[ $object['type'] ] = [];
	}

	$groups = [];
	$fields = [];

	if ( isset( $object['groups'] ) ) {
		$groups = $object['groups'];

		unset( $object['groups'] );
	}

	if ( isset( $object['fields'] ) ) {
		$fields = $object['fields'];

		unset( $object['fields'] );
	}

	// Maybe set the code source for this type.
	if (
		! isset( $object['_pods_code_source'] )
		&& (
			! isset( $object['object_storage_type'] )
			|| 'file' !== $object['object_storage_type']
		)
	) {
		$debug_info = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 3 );

		foreach ( $debug_info as $debug ) {
			// Skip Pods-related and WP-related hook registrations.
			if ( 0 === strpos( $debug['file'], PODS_DIR ) || 0 === strpos( $debug['file'], WPINC ) ) {
				continue;
			}

			$object['_pods_code_source'] = sprintf(
				'%s : %s %d',
				$debug['file'],
				esc_html__( 'Line', 'pods' ),
				$debug['line']
			);

			break;
		}
	}

	$registered = pods_register_object( $object, 'pod' );

	if ( true === $registered ) {
		try {
			$object_collection = Store::get_instance();

			$registered_object = $object_collection->get_object( 'pod/' . $object['name'] );

			if ( $registered_object ) {
				PodsMeta::$queue[ $object['type'] ][ $object['name'] ] = $registered_object;
			}
		} catch ( Exception $exception ) {
			return new WP_Error( 'pods-register-type-error', $exception->getMessage() );
		}
	}

	foreach ( $groups as $group ) {
		pods_register_group( $group, $object['name'] );
	}

	foreach ( $fields as $field ) {
		pods_register_field( $object['name'], $field['name'], $field );
	}

	return $registered;
}

/**
 * Add a new Pod field outside of the DB.
 *
 * @see   PodsMeta::register_field
 *
 * @param string|array $pod    The pod name or array of pod names
 * @param string       $name   The name of the Pod
 * @param array        $object (optional) Pod array, including any 'fields' arrays
 *
 * @return array|boolean|WP_Error Field data or WP_Error if unsuccessful.
 * @since 2.1.0
 */
function pods_register_field( $pod, $name, $field = null ) {
	$pod_name = is_string( $pod ) ? $pod : $pod['name'];

	if ( empty( $field ) ) {
		$field = [];
	}

	if ( ! empty( $name ) ) {
		$field['name'] = $name;
	}

	$field['parent'] = 'pod/' . $pod_name;

	return pods_register_object( $field, 'field' );
}

/**
 * Add a new Pod field type
 *
 * @see   PodsForm::register_field_type
 *
 * @param string $type The new field type identifier
 * @param string $file The new field type class file location
 *
 * @return array Field type array
 * @since 2.3.0
 */
function pods_register_field_type( $type, $file = null ) {
	return PodsForm::register_field_type( $type, $file );
}

/**
 * Register a related object
 *
 * @param string $name    Object name
 * @param string $label   Object label
 * @param array  $options Object options
 *
 * @return array|boolean Object array or false if unsuccessful
 * @since 2.3.0
 */
function pods_register_related_object( $name, $label, $options = null ) {
	return PodsForm::field_method( 'pick', 'register_related_object', $name, $label, $options );
}

/**
 * Register an object with Pods.
 *
 * @since 2.8.0
 *
 * @param array  $object The object configuration.
 * @param string $type   The object type.
 *
 * @return true|WP_Error True if successful, or else an WP_Error with the problem.
 */
function pods_register_object( array $object, $type ) {
	$object['object_type'] = $type;

	if ( ! isset( $object['object_storage_type'] ) || 'post_type' === $object['object_storage_type'] ) {
		$object['object_storage_type'] = 'collection';
	}

	try {
		$object_collection = Store::get_instance();
		$object_collection->register_object( $object );
	} catch ( Exception $exception ) {
		return new WP_Error( 'pods-register-object-error', $exception->getMessage() );
	}

	return true;
}

/**
 * Register a group and it's fields with Pods.
 *
 * @since 2.8.0
 *
 * @param array  $group The group configuration.
 * @param string $pod   The pod to register to.
 * @param array  $field The list of group fields.
 *
 * @return true|WP_Error True if successful, or else an WP_Error with the problem.
 */
function pods_register_group( array $group, $pod, array $fields = [] ) {
	$pod_name = is_string( $pod ) ? $pod : $pod['name'];

	$group['parent'] = 'pod/' . $pod_name;

	if ( isset( $group['fields'] ) ) {
		$fields = $group['fields'];

		unset( $group['fields'] );
	}

	pods_register_object( $group, 'group' );

	foreach ( $fields as $field ) {
		pods_register_group_field( $field, $group['name'], $pod_name );
	}

	return true;
}

/**
 * Register a field with Pods.
 *
 * @since 2.8.0
 *
 * @param array  $field The field configuration.
 * @param string $group The group to register to.
 * @param string $pod   The pod to register to.
 *
 * @return true|WP_Error True if successful, or else an WP_Error with the problem.
 */
function pods_register_group_field( array $field, $group, $pod ) {
	$pod_name = is_string( $pod ) ? $pod : $pod['name'];

	$field['parent'] = 'pod/' . $pod_name;
	$field['group']  = $group;

	pods_register_object( $field, 'field' );

	return true;
}

/**
 * Register a block type with Pods. Always register during the `pods_blocks_api_init` action.
 *
 * @since 2.8.0
 *
 * @param array $block  The block configuration, compatible with `register_block_type()`.
 * @param array $fields List of fields to use for inspector controls.
 *
 * @return true|WP_Error True if successful, or else an WP_Error with the problem.
 *
 * @see register_block_type
 * @see Pods\Blocks\Types\Base
 */
function pods_register_block_type( array $block, array $fields = [] ) {
	if ( empty( $block['namespace'] ) ) {
		return new WP_Error( 'pods-blocks-api-block-type-invalid', __( 'Invalid block type configuration provided', 'pods' ) );
	}

	$block['object_type']  = 'block';
	$block['object_storage_type'] = 'collection';
	$block['name']         = pods_v( 'name', $block, pods_v( 'slug', $block ) );
	$block['label']        = pods_v( 'label', $block, pods_v( 'title', $block ) );
	$block['category']     = pods_v( 'category', $block, pods_v( 'collection', $block ) );

	$object_collection = Store::get_instance();
	$object_collection->register_object( $block );

	foreach ( $fields as $field ) {
		$field['object_type']  = 'block-field';
		$field['object_storage_type'] = 'collection';
		$field['parent']       = 'block/' . $block['name'];
		$field['name']         = pods_v( 'name', $field, pods_v( 'slug', $field ) );
		$field['label']        = pods_v( 'label', $field, pods_v( 'title', $field ) );

		$object_collection->register_object( $field );
	}

	return true;
}

/**
 * Register a block collection with Pods. Always register during the `pods_blocks_api_init` action.
 *
 * @since 2.8.0
 *
 * @param array $collection The block collection configuration, compatible with `block_categories` filter.
 *
 * @return true|WP_Error True if successful, or else an WP_Error with the problem.
 *
 * @see Pods\Blocks\Collections\Base
 */
function pods_register_block_collection( array $collection ) {
	if ( empty( $collection['namespace'] ) ) {
		return new WP_Error( 'pods-blocks-api-block-collection-invalid', __( 'Invalid block collection configuration provided', 'pods' ) );
	}

	$collection['object_type']  = 'block-collection';
	$collection['object_storage_type'] = 'collection';
	$collection['label']        = pods_v( 'label', $collection, pods_v( 'title', $collection ) );

	$object_collection = Store::get_instance();
	$object_collection->register_object( $collection );

	return true;
}

/**
 * Register a custom config file to use with Pods configs.
 *
 * @since 2.9.0
 *
 * @param string $file        The config file to use.
 * @param string $config_type The config file type to use (defaults to json).
 */
function pods_register_config_file( $file, $config_type = 'json' ) {
	try {
		$config_handler = pods_container( Config_Handler::class );

		$config_handler->register_file( $file, $config_type );
	} catch ( Exception $exception ) {
		// Container does not exist yet, we cannot do anything at this point.
	}
}

/**
 * Register a custom config path to use with Pods configs.
 *
 * @since 2.9.0
 *
 * @param string $path The config path to use.
 */
function pods_register_config_path( $path ) {
	try {
		$config_handler = pods_container( Config_Handler::class );

		$config_handler->register_path( $path );
	} catch ( Exception $exception ) {
		// Container does not exist yet, we cannot do anything at this point.
	}
}

/**
 * Register a custom config type to use with Pods configs.
 *
 * For custom config types, use the pods_config_parse_$type filter along with this to support other format parsing.
 *
 * Default support for json and yml can be filtered with the pods_config_parse filter to override them.
 *
 * @since 2.9.0
 *
 * @param string $type The config type to use.
 */
function pods_register_config_type( $type ) {
	try {
		$config_handler = pods_container( Config_Handler::class );

		$config_handler->register_config_type( $type );
	} catch ( Exception $exception ) {
		// Container does not exist yet, we cannot do anything at this point.
	}
}

/**
 * Register a custom config item type to use with Pods configs.
 *
 * @since 2.9.0
 *
 * @param string $item_type The config path to use.
 */
function pods_register_config_item_type( $item_type ) {
	try {
		$config_handler = pods_container( Config_Handler::class );

		$config_handler->register_config_item_type( $item_type );
	} catch ( Exception $exception ) {
		// Container does not exist yet, we cannot do anything at this point.
	}
}

/**
 * Require a component (always-on)
 *
 * @param string $component Component ID
 *
 * @return void
 *
 * @since 2.3.0
 */
function pods_require_component( $component ) {
	add_filter( 'pods_component_require_' . $component, '__return_true' );
}

/**
 * Add a meta group of fields to add/edit forms
 *
 * @see   PodsMeta::group_add
 *
 * @param string|array $pod      The pod or type of element to attach the group to.
 * @param string       $label    Title of the edit screen section, visible to user.
 * @param string|array $fields   Either a comma separated list of text fields or an associative array containing field
 *                               information.
 * @param string       $context  (optional) The part of the page where the edit screen section should be shown
 *                               ('normal', 'advanced', or 'side').
 * @param string       $priority (optional) The priority within the context where the boxes should show ('high',
 *                               'core', 'default' or 'low').
 * @param string       $type     (optional) Type of the post to attach to.
 *
 * @return void
 *
 * @since 2.0.0
 * @link  https://docs.pods.io/code/general-functions/pods-group-add/
 */
function pods_group_add( $pod, $label, $fields, $context = 'normal', $priority = 'default', $type = null ) {
	pods_meta()->group_add( $pod, $label, $fields, $context, $priority );
}

/**
 * Check if a plugin is active on non-admin pages (is_plugin_active() only available in admin)
 *
 * @param string $plugin Plugin name.
 *
 * @return bool
 *
 * @since 2.0.0
 */
function pods_is_plugin_active( $plugin ) {
	$active = false;

	if ( function_exists( 'is_plugin_active' ) ) {
		$active = is_plugin_active( $plugin );
	}

	if ( ! $active ) {
		$active_plugins = (array) get_option( 'active_plugins', array() );

		if ( in_array( $plugin, $active_plugins, true ) ) {
			$active = true;
		}

		if ( ! $active && is_multisite() ) {
			$plugins = get_site_option( 'active_sitewide_plugins' );

			if ( isset( $plugins[ $plugin ] ) ) {
				$active = true;
			}
		}
	}

	return $active;
}

/**
 * Check if Pods no conflict is on or not.
 *
 * Note: $object_type in the future may be default to null instead of 'post'.
 *
 * @param string|null $object_type The object type to check if no conflict is on for.
 *
 * @return bool Whether no conflict is on.
 *
 * @since 2.3.0
 */
function pods_no_conflict_check( $object_type = 'post' ) {
	if ( 'post_type' === $object_type ) {
		$object_type = 'post';
	} elseif ( 'term' === $object_type ) {
		$object_type = 'taxonomy';
	}

	if ( ! class_exists( 'PodsInit' ) ) {
		pods_init();
	}

	if ( empty( $object_type ) ) {
		return ! empty( PodsInit::$no_conflict );
	}

	if ( ! empty( PodsInit::$no_conflict[ $object_type ] ) ) {
		return true;
	}

	return false;
}

/**
 * Get the list of meta hooks to add/remove for a specific object type.
 *
 * @since 2.8.0
 *
 * @param string      $object_type The object type.
 * @param string|null $object      The object name.
 *
 * @return array List of filters and actions for a specific object type.
 */
function pods_meta_hook_list( $object_type = 'post', $object = null ) {
	if ( 'post_type' === $object_type ) {
		$object_type = 'post';
	} elseif ( 'term' === $object_type ) {
		$object_type = 'taxonomy';
	}

	$hooks = [
		'filter' => [],
		'action' => [],
	];

	// If Pods is not being used for any fields, bypass all hooks.
	if ( pods_is_types_only() ) {
		return $hooks;
	}

	$first_pods_version = get_option( 'pods_framework_version_first' );
	$first_pods_version = '' === $first_pods_version ? PODS_VERSION : $first_pods_version;

	$metadata_integration = 1 === (int) pods_get_setting( 'metadata_integration', 1 );
	$watch_changed_fields = 1 === (int) pods_get_setting( 'watch_changed_fields', version_compare( $first_pods_version, '2.8.21', '<=' ) ? 1 : 0 );

	$is_tableless = pods_tableless();

	// Filters = Usually get/update/delete meta functions
	// Actions = Usually insert/update/save/delete object functions
	if ( 'post' === $object_type || 'media' === $object_type  || 'all' === $object_type ) {
		// Handle *_post_meta
		if ( $metadata_integration && apply_filters( 'pods_meta_handler', true, 'post' ) ) {
			if ( apply_filters( 'pods_meta_handler_get', true, 'post' ) ) {
				$hooks['filter']['get_post_metadata'] = [ 'get_post_metadata', [ PodsInit::$meta, 'get_post_meta' ], 10, 4 ];
			}

			if ( ! $is_tableless ) {
				$hooks['filter']['add_post_metadata']          = [ 'add_post_metadata', [ PodsInit::$meta, 'add_post_meta' ], 10, 5 ];
				$hooks['filter']['update_post_metadata']       = [ 'update_post_metadata', [ PodsInit::$meta, 'update_post_meta' ], 10, 5 ];
				$hooks['filter']['update_post_metadata_by_id'] = [ 'update_post_metadata_by_id', [ PodsInit::$meta, 'update_post_meta_by_id' ], 10, 4 ];
				$hooks['filter']['delete_post_metadata']       = [ 'delete_post_metadata', [ PodsInit::$meta, 'delete_post_meta' ], 10, 5 ];
				$hooks['filter']['delete_post_metadata_by_id'] = [ 'delete_post_metadata_by_id', [ PodsInit::$meta, 'delete_post_meta_by_id' ], 10, 2 ];
			}
		}

		// Add meta box groups.
		$hooks['action'][] = [ 'add_meta_boxes', [ PodsInit::$meta, 'meta_post_add' ], 10, 1 ];

		// Other post-related hooks.
		$hooks['filter'][] = [ 'enter_title_here', [ PodsInit::$meta, 'meta_post_enter_title_here' ], 10, 2 ];
		$hooks['filter'][] = [ 'wp_revisions_to_keep', [ PodsInit::$meta, 'meta_post_revisions_to_keep' ], 10, 2 ];

		if ( 'post' === $object_type || 'all' === $object_type ) {
			// Handle detecting new post.
			$hooks['action'][] = [ 'transition_post_status', [ PodsInit::$meta, 'save_post_detect_new' ], 10, 3 ];

			// Handle save.
			$hooks['action'][] = [ 'save_post', [ PodsInit::$meta, 'save_post' ], 10, 3 ];

			// Handle delete from relationships.
			$hooks['action'][] = [ 'delete_post', [ PodsInit::$meta, 'delete_post' ], 10, 1 ];

			if ( $watch_changed_fields ) {
				// Track changed fields.
				$hooks['action'][] = [
					'wp_insert_post_data',
					[ PodsInit::$meta, 'save_post_track_changed_fields' ],
					10,
					2,
				];
			}
		}
	}

	if ( 'taxonomy' === $object_type || 'all' === $object_type ) {
		// Handle *_term_meta
		if ( $metadata_integration && apply_filters( 'pods_meta_handler', true, 'term' ) ) {
			if ( apply_filters( 'pods_meta_handler_get', true, 'term' ) ) {
				$hooks['filter'][] = [ 'get_term_metadata', [ PodsInit::$meta, 'get_term_meta' ], 10, 4 ];
			}

			if ( ! $is_tableless ) {
				$hooks['filter']['add_term_metadata']          = [ 'add_term_metadata', [ PodsInit::$meta, 'add_term_meta' ], 10, 5 ];
				$hooks['filter']['update_term_metadata']       = [ 'update_term_metadata', [ PodsInit::$meta, 'update_term_meta' ], 10, 5 ];
				$hooks['filter']['update_term_metadata_by_id'] = [ 'update_term_metadata_by_id', [ PodsInit::$meta, 'update_term_meta_by_id' ], 10, 4 ];
				$hooks['filter']['delete_term_metadata']       = [ 'delete_term_metadata', [ PodsInit::$meta, 'delete_term_meta' ], 10, 5 ];
				$hooks['filter']['delete_term_metadata_by_id'] = [ 'delete_term_metadata_by_id', [ PodsInit::$meta, 'delete_term_meta_by_id' ], 10, 2 ];
			}
		}

		// Handle save.
		$hooks['action'][] = [ 'edited_term', [ PodsInit::$meta, 'save_taxonomy' ], 10, 3 ];
		$hooks['action'][] = [ 'create_term', [ PodsInit::$meta, 'save_taxonomy' ], 10, 3 ];

		// Handle delete from relationships.
		$hooks['action'][] = [ 'delete_term_taxonomy', [ PodsInit::$meta, 'delete_taxonomy' ], 10, 1 ];

		// Handle form fields specific to the taxonomy.
		if ( $object ) {
			$hooks['action'][] = [ $object . '_edit_form_fields', [ PodsInit::$meta, 'meta_taxonomy' ], 10, 2 ];
			$hooks['action'][] = [ $object . '_add_form_fields', [ PodsInit::$meta, 'meta_taxonomy' ], 10, 1 ];
		}

		if ( $watch_changed_fields ) {
			// Track changed fields.
			$hooks['action'][] = [
				'edit_terms',
				[ PodsInit::$meta, 'save_taxonomy_track_changed_fields' ],
				10,
				2,
			];
		}

		/**
		 * Fires after a previously shared taxonomy term is split into two separate terms.
		 *
		 * @since 4.2.0
		 *
		 * @param int    $term_id          ID of the formerly shared term.
		 * @param int    $new_term_id      ID of the new term created for the $term_taxonomy_id.
		 * @param int    $term_taxonomy_id ID for the term_taxonomy row affected by the split.
		 * @param string $taxonomy         Taxonomy for the split term.
		 */
		$hooks['action'][] = [ 'split_shared_term', [ PodsInit::$meta, 'split_shared_term' ], 10, 4 ];
	}

	if ( 'media' === $object_type || 'all' === $object_type ) {
		// Handle old AJAX attachment saving.
		$hooks['action'][] = [ 'wp_ajax_save-attachment-compat', [ PodsInit::$meta, 'save_media_ajax' ], 0, 1 ];

		// Handle showing meta fields in modal.
		$hooks['filter'][] = [ 'attachment_fields_to_edit', [ PodsInit::$meta, 'meta_media' ], 10, 2 ];

		// Handle saving meta fields from modal.
		$hooks['filter'][] = [ 'attachment_fields_to_save', [ PodsInit::$meta, 'save_media' ], 10, 2 ];

		// Handle saving attachment metadata.
		$hooks['filter'][] = [ 'wp_update_attachment_metadata', [ PodsInit::$meta, 'save_media' ], 10, 2 ];

		// Handle delete.
		$hooks['action'][] = [ 'delete_attachment', [ PodsInit::$meta, 'delete_media' ], 10, 1 ];

		if ( $watch_changed_fields ) {
			// Track changed fields.
			$hooks['filter'][] = [
				'wp_insert_attachment_data',
				[ PodsInit::$meta, 'save_post_track_changed_fields' ],
				10,
				2,
			];
		}
	}

	if ( 'user' === $object_type || 'all' === $object_type ) {
		// Handle *_user_meta.
		if ( $metadata_integration && apply_filters( 'pods_meta_handler', true, 'user' ) ) {
			if ( apply_filters( 'pods_meta_handler_get', true, 'user' ) ) {
				$hooks['filter'][] = [ 'get_user_metadata', [ PodsInit::$meta, 'get_user_meta' ], 10, 4 ];
			}

			if ( ! $is_tableless ) {
				$hooks['filter']['add_user_metadata']          = [ 'add_user_metadata', [ PodsInit::$meta, 'add_user_meta' ], 10, 5 ];
				$hooks['filter']['update_user_metadata']       = [ 'update_user_metadata', [ PodsInit::$meta, 'update_user_meta' ], 10, 5 ];
				$hooks['filter']['update_user_metadata_by_id'] = [ 'update_user_metadata_by_id', [ PodsInit::$meta, 'update_user_meta_by_id' ], 10, 4 ];
				$hooks['filter']['delete_user_metadata']       = [ 'delete_user_metadata', [ PodsInit::$meta, 'delete_user_meta' ], 10, 5 ];
				$hooks['filter']['delete_user_metadata_by_id'] = [ 'delete_user_metadata_by_id', [ PodsInit::$meta, 'delete_user_meta_by_id' ], 10, 2 ];
			}
		}

		// Handle showing fields in form.
		$hooks['action'][] = [ 'show_user_profile', [ PodsInit::$meta, 'meta_user' ], 10, 1 ];
		$hooks['action'][] = [ 'edit_user_profile', [ PodsInit::$meta, 'meta_user' ], 10, 1 ];

		// Handle saving from registration form.
		$hooks['action'][] = [ 'user_register', [ PodsInit::$meta, 'save_user' ], 10, 1 ];

		// Handle saving from profile update.
		$hooks['action'][] = [ 'profile_update', [ PodsInit::$meta, 'save_user' ], 10, 2 ];

		if ( $watch_changed_fields ) {
			// Track changed fields.
			$hooks['filter'][] = [
				'pre_user_login',
				[ PodsInit::$meta, 'save_user_track_changed_fields' ],
				10,
				1,
			];
		}
	}

	if ( 'comment' === $object_type || 'all' === $object_type ) {
		if ( $metadata_integration && apply_filters( 'pods_meta_handler', true, 'comment' ) ) {
			// Handle *_comment_meta
			if ( apply_filters( 'pods_meta_handler_get', true, 'comment' ) ) {
				$hooks['filter'][] = [ 'get_comment_metadata', [ PodsInit::$meta, 'get_comment_meta' ], 10, 4 ];
			}

			if ( ! $is_tableless ) {
				$hooks['filter']['add_comment_metadata']           = [ 'add_comment_metadata', [ PodsInit::$meta, 'add_comment_meta' ], 10, 5 ];
				$hooks['filter']['update_comment_metadata']        = [ 'update_comment_metadata', [ PodsInit::$meta, 'update_comment_meta' ], 10, 5 ];
				$hooks['filter']['update_comment_metadata_by_id']  = [ 'update_comment_metadata_by_id', [ PodsInit::$meta, 'update_comment_meta_by_id' ], 10, 4 ];
				$hooks['filter']['delete_comment_metadata']        = [ 'delete_comment_metadata', [ PodsInit::$meta, 'delete_comment_meta' ], 10, 5 ];
				$hooks['filter']['delete_comment_metadata_by_id']  = [ 'delete_comment_metadata_by_id', [ PodsInit::$meta, 'delete_comment_meta_by_id' ], 10, 2 ];
			}
		}

		// Handle showing fields in form.
		$hooks['filter'][] = [ 'comment_form_submit_field', [ PodsInit::$meta, 'meta_comment_new' ], 10, 1 ];

		// Add meta box groups.
		$hooks['action'][] = [ 'add_meta_boxes_comment', [ PodsInit::$meta, 'meta_comment_add' ], 10, 1 ];

		// Handle validation for fields.
		$hooks['filter'][] = [ 'pre_comment_approved', [ PodsInit::$meta, 'validate_comment' ], 10, 2 ];

		// Handle saving comment from frontend.
		$hooks['action'][] = [ 'comment_post', [ PodsInit::$meta, 'save_comment' ], 10, 1 ];

		// Handle saving comment from admin.
		$hooks['action'][] = [ 'edit_comment', [ PodsInit::$meta, 'save_comment' ], 10, 1 ];

		if ( $watch_changed_fields ) {
			// Track changed fields.
			$hooks['action'][] = [
				'wp_update_comment_data',
				[ PodsInit::$meta, 'save_comment_track_changed_fields' ],
				10,
				3,
			];
		}
	}

	if ( 'settings' === $object_type || 'all' === $object_type ) {
		// @todo Patch core to provide $option back in filters, patch core to add filter pre_add_option to add_option.

		// Undesirable way to do things which is heavy and requires access to looping through all fields, pulled from PodsMeta::core().
		/*foreach ( self::$settings as $setting_pod ) {
			foreach ( $setting_pod[ 'fields' ] as $option ) {
				add_filter( 'pre_option_' . $setting_pod[ 'name' ] . '_' . $option[ 'name' ], array( PodsInit::$meta, 'get_option' ), 10, 1 );
				add_action( 'add_option_' . $setting_pod[ 'name' ] . '_' . $option[ 'name' ], array( PodsInit::$meta, 'add_option' ), 10, 2 );
				add_filter( 'pre_update_option_' . $setting_pod[ 'name' ] . '_' . $option[ 'name' ], array( PodsInit::$meta, 'update_option' ), 10, 2 );
			}
		}*/
	}

	/**
	 * Allow filtering the list of actions and filters for a specific object type.
	 *
	 * @since 2.8.11
	 *
	 * @param array       $hooks       List of filters and actions for a specific object type.
	 * @param string      $object_type The object type.
	 * @param string|null $object      The object name.
	 */
	return (array) apply_filters( 'pods_meta_hook_list', $hooks, $object_type );
}

/**
 * Turn off conflicting / recursive actions for an object type that Pods hooks into
 *
 * @since 2.0.0
 *
 * @param string      $object_type The object type.
 * @param string|null $object      The object name.
 *
 * @return bool Whether no conflict mode was turned on.
 */
function pods_no_conflict_on( $object_type = 'post', $object = null ) {
	if ( 'post_type' === $object_type ) {
		$object_type = 'post';
	} elseif ( 'term' === $object_type ) {
		$object_type = 'taxonomy';
	}

	if ( ! class_exists( 'PodsInit' ) ) {
		pods_init();
	}

	if ( ! empty( PodsInit::$no_conflict[ $object_type ] ) ) {
		return true;
	}

	if ( ! is_object( PodsInit::$meta ) ) {
		return false;
	}

	$no_conflict = pods_meta_hook_list( $object_type );

	$conflicted = false;

	foreach ( $no_conflict as $action_filter => $conflicts ) {
		foreach ( $conflicts as $k => $args ) {
			if ( call_user_func_array( 'has_' . $action_filter, array_slice( $args, 0, 2 ) ) ) {
				call_user_func_array( 'remove_' . $action_filter, array_slice( $args, 0, 3 ) );

				$conflicted = true;
			} else {
				unset( $no_conflict[ $action_filter ][ $k ] );
			}
		}
	}

	if ( $conflicted ) {
		PodsInit::$no_conflict[ $object_type ] = $no_conflict;

		return true;
	}

	return false;
}

/**
 * Turn on actions after running code during pods_conflict
 *
 * @since 2.0.0
 *
 * @param string      $object_type The object type.
 * @param string|null $object      The object name.
 * @param bool        $force       Whether to force turning all hooks back on even if they were already off.
 *
 * @return bool Whether no conflict mode was on and was successfully turned off.
 */
function pods_no_conflict_off( $object_type = 'post', $object = null, $force = false ) {
	if ( 'post_type' === $object_type ) {
		$object_type = 'post';
	} elseif ( 'term' === $object_type ) {
		$object_type = 'taxonomy';
	}

	if ( ! class_exists( 'PodsInit' ) ) {
		pods_init();
	}

	if ( ! is_object( PodsInit::$meta ) ) {
		return false;
	}

	if ( $force ) {
		// Turn ALL hooks back on.
		$no_conflict = pods_meta_hook_list( $object_type, $object );
	} else {
		// No conflict mode was not already on.
		if ( empty( PodsInit::$no_conflict[ $object_type ] ) ) {
			return false;
		}

		// Only turn on the hooks we turned off for no conflict mode.
		$no_conflict = PodsInit::$no_conflict[ $object_type ];
	}

	$conflicted = false;

	foreach ( $no_conflict as $action_filter => $conflicts ) {
		foreach ( $conflicts as $args ) {
			if ( ! call_user_func_array( 'has_' . $action_filter, array_slice( $args, 0, 2 ) ) ) {
				call_user_func_array( 'add_' . $action_filter, $args );

				$conflicted = true;
			}
		}
	}

	if ( isset( PodsInit::$no_conflict['all'] ) ) {
		unset( PodsInit::$no_conflict['all'] );
	}

	if ( $conflicted ) {
		unset( PodsInit::$no_conflict[ $object_type ] );

		return true;
	}

	return false;
}

/**
 * Returns a list of all WordPress and Pods reserved keywords.
 *
 * @link https://codex.wordpress.org/Reserved_Terms
 *
 * @since 2.7.15
 *
 * @param null|string $context The reserved keyword context.
 *
 * @return array
 */
function pods_reserved_keywords( $context = null ) {
	// WordPress Post keywords.
	$wp_post_keywords = [
		'id',
		'ID',
		'attachment',
		'attachment_id',
		'author',
		'author_name',
		'category',
		'link_category',
		'name',
		'p',
		'page',
		'paged',
		'post',
		'post_format',
		'post_mime_type',
		'post_status',
		'post_tag',
		'post_thumbnail',
		'post_thumbnail_url',
		'post_type',
		's',
		'search',
		'tag',
		'taxonomy',
		'term',
		'terms',
		'title',
		'type',
	];

	// WordPress keywords.
	$wp_keywords = [
		'calendar',
		'cat',
		'category__and',
		'category__in',
		'category__not_in',
		'category_name',
		'comments_per_page',
		'comments_popup',
		'cpage',
		'custom',
		'customize_messenger_channel',
		'customized',
		'day',
		'debug',
		'embed',
		'error',
		'exact',
		'feed',
		'hour',
		'm',
		'minute',
		'monthnum',
		'more',
		'nav_menu',
		'nonce',
		'nopaging',
		'offset',
		'order',
		'orderby',
		'page_id',
		'pagename',
		'pb',
		'perm',
		'post__in',
		'post__not_in',
		'posts',
		'posts_per_archive_page',
		'posts_per_page',
		'preview',
		'robots',
		'second',
		'sentence',
		'showposts',
		'static',
		'subpost',
		'subpost_id',
		'tag__and',
		'tag__in',
		'tag__not_in',
		'tag_id',
		'tag_slug__and',
		'tag_slug__in',
		'tb',
		'theme',
		'w',
		'withcomments',
		'withoutcomments',
		'year',
	];

	// Pods keywords.
	$pods_keywords = [
		'id',
		'ID',
	];

	$keywords = [];

	// Add keywords for WP context.
	if ( in_array( $context, [ null, 'wp' ], true ) ) {
		$keywords = array_merge( $keywords, $wp_keywords );
	}

	// Add keywords for WP Post contexts (also applies to WP context).
	if ( in_array( $context, [ null, 'wp', 'wp-post' ], true ) ) {
		$keywords = array_merge( $keywords, $wp_post_keywords );
	}

	// Add keywords for Pods context.
	if ( in_array( $context, [ null, 'pods' ], true ) ) {
		$keywords = array_merge( $keywords, $pods_keywords );
	}

	$keywords = array_filter( array_unique( $keywords ) );

	/**
	 * Filter the WordPress and Pods reserved keywords.
	 *
	 * @since 2.7.15
	 *
	 * @param array       $keywords List of WordPress and Pods reserved keywords.
	 * @param null|string $context  The reserved keyword context.
	 */
	return apply_filters( 'pods_reserved_keywords', $keywords, $context );
}

/**
 * Get the value for a Pods setting.
 *
 * @since 2.8.0
 *
 * @param string $setting_name The setting name.
 * @param null   $default      The default value if the setting is not yet set.
 *
 * @return mixed The setting value.
 */
function pods_get_setting( $setting_name, $default = null ) {
	$settings = pods_container( Settings::class );

	// Fallback for the setting handling if it's too early.
	if ( ! $settings ) {
		$settings = get_option( Settings::OPTION_NAME, [] );

		$setting = pods_v( $setting_name, (array) $settings, $default );

		if ( null !== $default && ( null === $setting || '' === $setting ) ) {
			return $default;
		}

		return $setting;
	}

	return $settings->get_setting( $setting_name, $default );
}

/**
 * Get the Pods settings.
 *
 * @since 2.8.0
 *
 * @return array The setting values.
 */
function pods_get_settings() {
	$settings = pods_container( Settings::class );

	return $settings->get_settings();
}

/**
 * Update the value for a Pods setting.
 *
 * @since 2.8.0
 *
 * @param string $setting_name  The setting name.
 * @param mixed  $setting_value The setting value.
 */
function pods_update_setting( $setting_name, $setting_value ) {
	$settings = pods_container( Settings::class );

	$settings->update_setting( $setting_name, $setting_value );
}

/**
 * Update the settings for a Pods.
 *
 * @since 2.8.0
 *
 * @param array $setting_values The list of settings to update, pass null as a value to remove it.
 */
function pods_update_settings( $setting_values ) {
	$settings = pods_container( Settings::class );

	$settings->update_settings( $setting_values );
}

/**
 * Determine if Session Auto Start is enabled.
 *
 * @param bool $check_constant_only Whether to only check the constant.
 *
 * @since 2.8.0
 *
 * @return bool|string|null Boolean if it is set to on or off, "auto" if set to auto, and null if $check_constant_only and constant is not set.
 */
function pods_session_auto_start( $check_constant_only = false ) {
	if ( defined( 'PODS_SESSION_AUTO_START' ) ) {
		return PODS_SESSION_AUTO_START;
	}

	if ( $check_constant_only ) {
		return null;
	}

	$auto_start = pods_get_setting( 'session_auto_start', 'auto' );

	// Check for "auto" string and return that.
	if ( 'auto' === $auto_start ) {
		return $auto_start;
	}

	return FILTER_VAR( $auto_start, FILTER_VALIDATE_BOOLEAN );
}

/**
 * Determine if we can use PHP sessions.
 *
 * @since 2.8.0
 *
 * @param bool $only_env_check Whether to ignore constant/option/logged in checks.
 *
 * @return bool Whether we can use sessions.
 */
function pods_can_use_sessions( $only_env_check = false ) {
	// Maybe check non-environment factors.
	if ( ! $only_env_check ) {
		// We do not need a session ID if there is a valid user logged in.
		if ( is_user_logged_in() ) {
			return false;
		}

		// Allow for bypassing Pods session auto-starting.
		if ( ! pods_session_auto_start() ) {
			return false;
		}
	}

	if ( ! defined( 'PANTHEON_SESSIONS_ENABLED' ) || ! PANTHEON_SESSIONS_ENABLED ) {
		// We aren't using Pantheon WP Native Sessions plugin so let's check if the normal session will work.

		$save_path = session_save_path();

		if ( ! function_exists( 'session_status' ) || PHP_SESSION_DISABLED === session_status() ) {
			// Sessions are disabled.
			return false;
		}

		if ( 0 === strpos( $save_path, 'tcp://' ) ) {
			// Allow for non-file based sessions, like Memcache.
			// This is OK, but we don't want to check if file_exists on next statement.
		} elseif ( empty( $save_path ) || ! @file_exists( $save_path ) || ! is_writable( $save_path ) ) {
			// Check if session path exists and can be written to, avoiding PHP fatal errors.
			return false;
		}
	}

	// Allow sessions.
	return true;
}

/**
 * Safely start a new session (without white screening on certain hosts,
 * which have no session path or the path is not writable).
 *
 * @since 2.3.10
 *
 * @return boolean Whether the session was started.
 */
function pods_session_start() {
	if ( function_exists( 'session_status' ) && PHP_SESSION_ACTIVE === session_status() ) {
		return true;
	}

	if ( false !== headers_sent() ) {
		// Check if headers were sent.
		return false;
	}

	if ( ! pods_can_use_sessions() ) {
		return false;
	}

	// Start session
	return @session_start();
}

/**
 * Get current session ID.
 *
 * @since 2.7.23
 *
 * @return string The session ID.
 */
function pods_session_id() {
	if ( false === pods_session_start() ) {
		return '';
	}

	return @session_id();
}

/**
 * @todo  : replace string literal with a defined constant
 *
 * @return bool
 *
 * @since 2.7.0
 */
function pods_is_modal_window() {
	$is_modal_window = false;

	if ( ! empty( $_GET['pods_modal'] ) || ! empty( $_POST['pods_modal'] ) ) {
		$is_modal_window = true;
	}

	return $is_modal_window;
}

/**
 * Check if the Pods object is exists and is valid.
 *
 * @param Pods|mixed $pod The Pods object or something that isn't a pod object.
 *
 * @return bool Whether the Pods object is exists and is valid.
 *
 * @since 2.7.0
 */
function pod_is_valid( $pod ) {
	return $pod instanceof Pods && $pod->valid();
}

/**
 * Check if the pod object has item(s).
 *
 * @param Pods|mixed $pod The pod object or something that isn't a pod object
 *
 * @return bool Whether the pod object has items
 *
 * @since 2.7.0
 */
function pod_has_items( $pod ) {
	if ( ! pod_is_valid( $pod ) ) {
		return false;
	}

	if (
		(
			$pod->id
			&& $pod->exists()
		)
		|| (
			! empty( $pod->params )
			&& 0 < $pod->total()
		)
	) {
		return true;
	}

	return false;
}

/**
 * Merge one config into another for purposes of overriding certain arguments.
 *
 * @since 2.8.0
 *
 * @param array|Field $config_to_merge_into The config to merge into.
 * @param array|Field $config_to_merge_from The config to merge from.
 *
 * @return array|Field The final config result.
 */
function pods_config_merge_data( $config_to_merge_into, $config_to_merge_from ) {
	// The configs already match.
	if ( $config_to_merge_into === $config_to_merge_from ) {
		return $config_to_merge_into;
	}

	// Merge the config into the destination config if both are Value_Field.
	if ( $config_to_merge_into instanceof Value_Field && $config_to_merge_from instanceof Value_Field ) {
		$field_object_into = $config_to_merge_into->get_field_object();
		$field_value_into  = $config_to_merge_into->get_field_value();

		$field_object_from = $config_to_merge_from->get_field_object();
		$field_value_from  = $config_to_merge_from->get_field_value();

		$config_to_merge_into->set_field_object( pods_config_merge_data( $field_object_into, $field_object_from ) );
		$config_to_merge_into->set_field_value( $field_value_from );

		return $config_to_merge_into;
	}

	// Merge the config into the destination config.
	if ( $config_to_merge_into instanceof Whatsit ) {
		return $config_to_merge_into->set_args( $config_to_merge_from );
	}

	// Merge the destination config into the config but don't replace data.
	if ( $config_to_merge_from instanceof Whatsit ) {
		return $config_to_merge_from->set_args( $config_to_merge_into, false );
	}

	// The config was not an array.
	if ( ! is_array( $config_to_merge_from ) ) {
		return $config_to_merge_into;
	}

	// The config was not an array.
	if ( ! is_array( $config_to_merge_into ) ) {
		return $config_to_merge_from;
	}

	// Merge the config arrays together.
	return array_merge( $config_to_merge_into, $config_to_merge_from );
}

/**
 * Merge multiple configs into others for purposes of overriding certain arguments.
 *
 * @since 2.8.0
 *
 * @param array[]|Field[] $configs_to_merge_into The configs to merge into.
 * @param array[]|Field[] $configs_to_merge_from The configs to merge from.
 *
 * @return array[]|Field[] The final config results.
 */
function pods_config_merge_fields( $configs_to_merge_into, $configs_to_merge_from ) {
	// The configs already match.
	if ( $configs_to_merge_into === $configs_to_merge_from ) {
		return $configs_to_merge_into;
	}

	foreach ( $configs_to_merge_from as $key => $config_to_merge_from ) {
		if ( ! isset( $config_to_merge_into[ $key ] ) ) {
			$configs_to_merge_into[ $key ] = $config_to_merge_from;

			continue;
		}

		$configs_to_merge_into[ $key ] = pods_config_merge_data( $config_to_merge_into[ $key ], $config_to_merge_from );
	}

	return $configs_to_merge_into;
}

/**
 * Get the list of all fields, including object fields, from a Pod configuration.
 *
 * @since 2.8.0
 *
 * @param array|Pod|Pods $pod The Pod configuration array or object.
 *
 * @return array[]|Field[] The list of all fields, including object fields.
 */
function pods_config_get_all_fields( $pod ) {
	$pod = pods_config_for_pod( $pod );

	if ( ! $pod ) {
		return [];
	}

	return $pod->get_all_fields();
}

/**
 * Get the field object from a value field object.
 *
 * @since 2.8.0
 *
 * @param Value_Field|Field $value_field The value field object.
 *
 * @return Field The field object.
 */
function pods_config_get_field_from_value_field( $value_field ) {
	// Maybe get the field object.
	if ( $value_field instanceof Value_Field ) {
		return $value_field->get_field_object();
	}

	return $value_field;
}

/**
 * Get the list of all field objects from a list of value field objects.
 *
 * @since 2.8.0
 *
 * @param Value_Field[]|Field[] $value_fields The list of value field objects.
 *
 * @return Field[] The list of all field objects.
 */
function pods_config_get_fields_from_value_fields( array $value_fields ) {
	$all_fields = [];

	foreach ( $value_fields as $key => $field ) {
		// Maybe get the field object.
		if ( $field instanceof Value_Field ) {
			$field = $field->get_field_object();
		}

		if ( is_int( $key ) ) {
			$all_fields[] = $field;
		} else {
			$all_fields[ $key ] = $field;
		}
	}

	return $all_fields;
}

/**
 * Get the field data for a specific field matching from all fields, including object fields, from a Pod configuration.
 *
 * @since 2.8.0
 *
 * @param string         $field The field name to get.
 * @param array|Pod|Pods $pod   The Pod configuration array or object.
 * @param null|string    $arg   The field argument to use when getting the field.
 *
 * @return array|Field|null The field data or null if not found.
 */
function pods_config_get_field_from_all_fields( $field, $pod, $arg = null ) {
	$pod = pods_config_for_pod( $pod );

	// The pod isn't there or valid.
	if ( empty( $pod ) ) {
		return null;
	}

	return $pod->get_field( $field );
}

/**
 * Get a normalized Pod configuration.
 *
 * @since 2.8.0
 *
 * @param Pod|Pods|array|string $pod   The Pod configuration object, Pods() object, old-style array, or name.
 *
 * @return false|Pod The Pod object or false if invalid.
 */
function pods_config_for_pod( $pod ) {
	if ( $pod instanceof Pod ) {
		return $pod;
	}

	if ( $pod instanceof Pods ) {
		// Check if the $pod is invalid.
		if ( ! $pod->valid() ) {
			return false;
		}

		return $pod->pod_data;
	}

	if ( is_string( $pod ) ) {
		try {
			$api = pods_api();

			$pod = $api->load_pod( [ 'name' => $pod ] );
		} catch ( Exception $exception ) {
			return false;
		}

		// Check if the $pod is invalid.
		if ( ! $pod ) {
			return false;
		}

		return $pod;
	}

	if ( ! is_array( $pod ) ) {
		return false;
	}

	$pod = new Pod( $pod );

	if ( ! $pod->is_valid() ) {
		return false;
	}

	return $pod;
}

/**
 * Get a normalized Field configuration.
 *
 * @since 2.9.8
 *
 * @param Field|array|string    $field The Field configuration object, Pods() object, old-style array, or name.
 * @param Pod|Pods|array|string $pod   The Pod configuration object, Pods() object, old-style array, or name.
 *
 * @return false|Field The Field object or false if invalid.
 */
function pods_config_for_field( $field, $pod = null ) {
	if ( $field instanceof Field ) {
		return $field;
	}

	if ( $pod ) {
		$pod = pods_config_for_pod( $pod );

		if ( ! $pod ) {
			$pod = null;
		}
	}

	if ( $pod && is_string( $field ) ) {
		$field = $pod->get_field( $field );

		// Check if the $field is invalid.
		if ( ! $field ) {
			return false;
		}

		return $field;
	}

	if ( ! is_array( $field ) ) {
		return false;
	}

	$field = new Field( $field );

	if ( ! $field->is_valid() ) {
		return false;
	}

	return $field;
}

function is_pods_alternative_cache_activated() {
	return function_exists( 'pods_alternative_cache_init' );
}

function is_pods_alternative_cache_activated_test() {
	$result = [
		'label'       => __( 'You are using the Pods Team recommended Pods Alternative Cache plugin', 'pods' ),
		'status'      => 'good',
		'badge'       => [
			'label' => __( 'Security' ),
			'color' => 'blue',
		],
		'description' => sprintf( '<p>%s</p>', __( 'The Pods Alternative Cache plugin is useful to many who use Pods.' ) ),
		'actions'     => sprintf( '<p><a href="%s">%s</a></p>', esc_url( admin_url( 'plugins.php' ) ), __( 'Manage your plugins' ) ),
		'test'        => 'is_pods_alternative_cache_activated',
	];

	return $result;
}

/**
 * Get the SVG icon data (base64 or svg itself) for the icon or the dashicon default class.
 *
 * @since 2.8.1
 *
 * @param string $icon_path The icon name or the SVG full file path to use.
 * @param string $default   The dashicons helper class (dashicons-database) to use if SVG not found.
 * @param string $mode      How to return the SVG (base64 or svg).
 *
 * @return string The SVG icon data (base64 or svg itself) for the icon or the dashicon default class.
 */
function pods_svg_icon( $icon_path, $default = 'dashicons-database', $mode = 'base64' ) {
	// Return the default when doing WP-CLI requests and Codeception testing.
	if ( ( defined( 'WP_CLI' ) && WP_CLI ) || function_exists( 'codecept_debug' ) ) {
		return $default;
	}

	if ( 'pods' === $icon_path ) {
		$icon_path = PODS_DIR . '/ui/images/icon-menu.svg';
	}

	$icon = pods_static_cache_get( $icon_path, __FUNCTION__ . '/' . $mode );

	// If the cached icon did not exist, use default.
	if ( '404-not-exists' === $icon ) {
		return $default;
	}

	// If the cached icon was found and is not empty, return it.
	if ( is_string( $icon ) && '' !== $icon ) {
		return $icon;
	}

	/**
	 * Allow filtering the SVG icon used and bypass the normal functionality.
	 *
	 * @since 2.8.2
	 *
	 * @param null|string $icon      The icon to use.
	 * @param string      $icon_path The SVG full file path to use.
	 * @param string      $default   The dashicons helper class (dashicons-database) to use if SVG not found.
	 * @param string      $mode      How to return the SVG (base64 or svg).
	 */
	$icon = apply_filters( 'pods_svg_icon', null, $icon_path, $default, $mode );

	if ( null !== $icon ) {
		return $icon;
	}

	if ( ! file_exists( $icon_path ) ) {
		pods_static_cache_set( '404-not-exists', $icon, __FUNCTION__ . '/' . $mode );

		return $default;
	}

	$svg_data = file_get_contents( $icon_path );

	if ( ! $svg_data ) {
		pods_static_cache_set( '404-not-exists', $icon, __FUNCTION__ . '/' . $mode );

		return $default;
	}

	pods_static_cache_set( $icon_path, $icon, __FUNCTION__ . '/' . $mode );

	// If mode is SVG data, return that.
	if ( 'svg' === $mode ) {
		return $svg_data;
	}

	// Default mode is base64.
	return 'data:image/svg+xml;base64,' . base64_encode( $svg_data );
}

/**
 * Determine whether Pods is being used for content types only.
 *
 * @since 2.8.11
 *
 * @param bool $check_constant_only Whether to only check the constant, unless there's a filter overriding things.
 *
 * @return bool Whether Pods is being used for content types only.
 */
function pods_is_types_only( $check_constant_only = false ) {
	// Check if Pods is only being used for content types only.
	if ( defined( 'PODS_META_TYPES_ONLY' ) && PODS_META_TYPES_ONLY ) {
		return true;
	}

	// Return null we want to only check the constant, unless there's a filter overriding things.
	if ( $check_constant_only && ! has_filter( 'pods_is_types_only' ) ) {
		return null;
	}

	$is_types_only = pods_get_setting( 'types_only', '0' );
	$is_types_only = filter_var( $is_types_only, FILTER_VALIDATE_BOOLEAN );

	/**
	 * Allow filtering whether Pods is being used for content types only.
	 *
	 * @since 2.8.11
	 *
	 * @param bool $is_types_only Whether Pods is being used for content types only.
	 */
	return (bool) apply_filters( 'pods_is_types_only', $is_types_only );
}

/**
 * Set up the container and return it.
 *
 * @since 2.8.17
 *
 * @param string|null $slug_or_class Either the slug of a binding previously registered using `tribe_singleton` or
 *                                   `tribe_register` or the full class name that should be automagically created or
 *                                   `null` to get the container instance itself.
 *
 * @return mixed|null The pods_container() object or null if the function does not exist yet.
 */
function pods_container( $slug_or_class = null ) {
	if ( ! function_exists( 'tribe' ) ) {
		_doing_it_wrong( __FUNCTION__, 'The function tribe() is not defined yet, there may be a problem loading the Tribe Common library.', '2.8.17' );

		return null;
	}

	return call_user_func_array( 'tribe', func_get_args() );
}