protected function get_row_results( $dbresults ) {
		$results   = [];
		$is_option = $this->get_meta_type() === 'option';

		foreach ( $dbresults as $meta ) {
			if ( $is_option ) {
				preg_match( '/^[^\d]*(\d+)/', $meta->option_name, $matches );
			} else {
				preg_match( '/^[^\d]*(\d+)/', $meta->meta_key, $matches );
			}

			if ( count( $matches ) < 2 ) {
				continue;
			}
			$i = intval( $matches[1] );

			if ( ! isset( $results[$i] ) ) {
				$results[$i] = [];
			}

			if ( $is_option ) {
				$results[$i][$meta->option_name] = (object) [
					'meta_key'   => $meta->option_name,
					'meta_value' => $meta->option_value
				];
			} else {
				$results[$i][$meta->meta_key] = $meta;
			}
		}

		return $results;
	}

protected function get_row_results ( $ dbresults ) { $ results = [ ] ; $ is_option = $ this -> get_meta_type ( ) === 'option' ; foreach ( $ dbresults as $ meta ) { if ( $ is_option ) { preg_match ( '/^[^\d]*(\d+)/' , $ meta -> option_name , $ matches ) ; } else { preg_match ( '/^[^\d]*(\d+)/' , $ meta -> meta_key , $ matches ) ; } if ( count ( $ matches ) < 2 ) { continue ; } $ i = intval ( $ matches [ 1 ] ) ; if ( ! isset ( $ results [ $ i ] ) ) { $ results [ $ i ] = [ ] ; } if ( $ is_option ) { $ results [ $ i ] [ $ meta -> option_name ] = ( object ) [ 'meta_key' => $ meta -> option_name , 'meta_value' => $ meta -> option_value ] ; } else { $ results [ $ i ] [ $ meta -> meta_key ] = $ meta ; } } return $ results ; }

Get row results.

@param  array $dbresults

@return array


public function load_value( $value, $repeater_slug, $post_id ) {
		if ( is_array( $value ) ) {
			return $value;
		}

		list( $results, $trash ) = $this->get_results( $value, $repeater_slug, $post_id );

		// Will not need this array.
		unset( $trash );

		$results = papi_from_property_array_slugs( $results, unpapify( $repeater_slug ) );

		if ( empty( $results ) ) {
			return $this->default_value;
		}

		return $this->load_child_properties( $results, $this );
	}

public
function
load_value
(
$
value
,
$
repeater_slug
,
$
post_id
)
{
if
(
is_array
(
$
value
)
)
{
return
$
value
;
}
list
(
$
results
,
$
trash
)
=
$
this
->
get_results
(
$
value
,
$
repeater_slug
,
$
post_id
)
;
// Will not need this array.
unset
(
$
trash
)
;
$
results
=
papi_from_property_array_slugs
(
$
results
,
unpapify
(
$
repeater_slug
)
)
;
if
(
empty
(
$
results
)
)
{
return
$
this
->
default_value
;
}
return
$
this
->
load_child_properties
(
$
results
,
$
this
)
;
}

Change value after it's loaded from the database
and populate every property in the repeater with the right property type.

@param int    $value
@param string $repeater_slug
@param int    $post_id

@return array

Change value after it s loaded from the database and populate every property in the repeater with the right property type .


protected function prepare_properties( $items ) {
		$key   = isset( $this->layout_key ) &&
		$this->layout_key === '_layout' ? 'flexible' : 'repeater';
		$items = array_map( 'papi_property', $items );

		$exclude_properties = $this->exclude_properties;
		$exclude_properties = array_merge( $exclude_properties, apply_filters( 'papi/property/' . $key . '/exclude', [] ) );

		return array_filter( $items, function ( $item ) use ( $exclude_properties ) {
			if ( ! is_object( $item ) ) {
				return false;
			}

			if ( empty( $item->type ) ) {
				return false;
			}

			return ! in_array( $item->type, $exclude_properties, true );
		} );
	}

protected function prepare_properties ( $ items ) { $ key = isset ( $ this -> layout_key ) && $ this -> layout_key === '_layout' ? 'flexible' : 'repeater' ; $ items = array_map ( 'papi_property' , $ items ) ; $ exclude_properties = $ this -> exclude_properties ; $ exclude_properties = array_merge ( $ exclude_properties , apply_filters ( 'papi/property/' . $ key . '/exclude' , [ ] ) ) ; return array_filter ( $ items , function ( $ item ) use ( $ exclude_properties ) { if ( ! is_object ( $ item ) ) { return false ; } if ( empty ( $ item -> type ) ) { return false ; } return ! in_array ( $ item -> type , $ exclude_properties , true ) ; } ) ; }

Prepare properties, get properties options object,
check which properties that are allowed to use.

@param  array $items

@return array

Prepare properties get properties options object check which properties that are allowed to use .


protected function prepare_property_for_json( $property ) {
		// Only real property objects and not properties that are disabled.
		if ( ! papi_is_property( $property ) || $property->disabled() ) {
			return false;
		}

		$options = clone $property->get_options();

		if ( isset( $options->settings->items ) ) {
			foreach ( $options->settings->items as $index => $property ) {
				if ( is_array( $property ) && isset( $property['items'] ) ) {
					foreach ( $property['items'] as $child_index => $child_property ) {
						$options->settings->items[$index]['items'][$child_index] = $this->prepare_property_for_json( $child_property );
					}
				}

				if ( $property = $this->prepare_property_for_json( $property ) ) {
					$options->settings->items[$index] = $property;
				}
			}
		}

		return $options;
	}

Prepare property for JSON.

@param  Papi_Property $property

@return bool|object


protected function remove_repeater_rows( $post_id, $repeater_slug ) {
		global $wpdb;

		$is_option     = $this->get_meta_type() === 'option';
		$repeater_slug = $repeater_slug . '_%';

		if ( $is_option ) {
			$table = $wpdb->prefix . 'options';

			// @codingStandardsIgnoreStart
			$query = $wpdb->prepare(
				"SELECT * FROM `$table` WHERE (`option_name` LIKE %s OR `option_name` LIKE %s AND NOT `option_name` = %s)",
				$repeater_slug,
				papi_f( $repeater_slug ),
				papi_get_property_type_key_f( $repeater_slug )
			);
			// @codingStandardsIgnoreEnd
		} else {
			$table = $wpdb->prefix . 'postmeta';
			// @codingStandardsIgnoreStart
			$query = $wpdb->prepare(
				"SELECT * FROM `$table` WHERE `post_id` = %d AND (`meta_key` LIKE %s OR `meta_key` LIKE %s AND NOT `meta_key` = %s)",
				$post_id,
				$repeater_slug,
				papi_f( $repeater_slug ),
				papi_get_property_type_key_f( $repeater_slug )
			);
			// @codingStandardsIgnoreEnd
		}

		$results = $wpdb->get_results( $query ); // WPCS: unprepared sql

		foreach ( $results as $res ) {
			if ( $is_option ) {
				$key = $res->option_name;
			} else {
				$key = $res->meta_key;
			}

			papi_data_delete( $post_id, $key, $this->get_meta_type() );
		}
	}

Remove all repeater rows from the database.

@param int    $post_id
@param string $repeater_slug

Remove all repeater rows from the database .


protected function render_json_template( $slug ) {
		$options = $this->get_options();

		$options->settings->items = papi_to_array( $options->settings->items );

		foreach ( $options->settings->items as $key => $value ) {
			$property = $this->prepare_property_for_json( papi_property( $value ) );

			if ( $property === false ) {
				unset( $options->settings->items[$key] );
				continue;
			}

			$options->settings->items[$key] = $property;
		}

		papi_render_html_tag( 'script', [
			'data-papi-json' => esc_attr( sprintf( '%s_repeater_json', $slug ) ),
			'type'           => 'application/json',
			papi_maybe_json_encode( [$options] )
		] );
	}

protected function render_json_template ( $ slug ) { $ options = $ this -> get_options ( ) ; $ options -> settings -> items = papi_to_array ( $ options -> settings -> items ) ; foreach ( $ options -> settings -> items as $ key => $ value ) { $ property = $ this -> prepare_property_for_json ( papi_property ( $ value ) ) ; if ( $ property === false ) { unset ( $ options -> settings -> items [ $ key ] ) ; continue ; } $ options -> settings -> items [ $ key ] = $ property ; } papi_render_html_tag ( 'script' , [ 'data-papi-json' => esc_attr ( sprintf ( '%s_repeater_json' , $ slug ) ) , 'type' => 'application/json' , papi_maybe_json_encode ( [ $ options ] ) ] ) ; }

Render property JSON template.

@param string $slug


protected function render_repeater_head() {
		$properties = $this->get_settings_properties();
		?>

		<?php if ( ! $this->layout( 'row' ) ): ?>

				<?php
				foreach ( $properties as $property ):
					// Don't show the property if it's disabled.
					if ( $property->disabled() ) {
						continue;
					}
					?>
					<th class="repeater-column <?php echo $property->display() ? '' : 'papi-hide'; ?>">
						<?php echo esc_html( $property->title ); ?>

				<?php endforeach; ?>

		<?php endif; ?>

		<?php
	}

?>
					<th class="repeater-column <?php


protected function render_repeater_rows() {
		$items  = $this->get_settings_properties();
		$values = $this->get_value();
		$values = is_array( $values ) ? $values : [];
		$slugs  = wp_list_pluck( $items, 'slug' );

		// Remove values that don't exists in the slugs array.
		foreach ( $values as $index => $value ) {
			if ( ! is_array( $value ) ) {
				continue;
			}

			$keys = array_keys( $value );

			foreach ( $slugs as $slug ) {
				if ( in_array( $slug, $keys, true ) ) {
					continue;
				}

				$values[$index][$slug] = '';
			}
		}

		$values      = array_filter( $values );
		$closed_rows = $this->get_setting( 'closed_rows', true );

		foreach ( $values as $row ):
			?>
			<tr <?php echo $closed_rows ? 'class="closed"' : ''; ?>>

					<?php echo esc_html( $this->counter + 1 ); ?>

				<?php
				$this->render_properties( $items, $row );
				$this->counter ++;
				?>

						<a title="<?php esc_attr_e( 'Remove', 'papi' ); ?>" href="#" class="repeater-remove-item">x

			<?php
		endforeach;
	}

?>" href="#" class="repeater-remove-item">x</a>
					</span>
				</td>
			</tr>
			<?php


public function register() {
		// Fetch all options entries.
		$this->entries = papi_get_all_entry_types( [
			'types' => 'option'
		] );

		foreach ( $this->entries as $entry ) {
			foreach ( $entry->get_properties() as $property ) {
				$property->register( 'option' );
			}
		}
	}

public
function
register
(
)
{
// Fetch all options entries.
$
this
->
entries
=
papi_get_all_entry_types
(
[
'types'
=>
'option'
]
)
;
foreach
(
$
this
->
entries
as
$
entry
)
{
foreach
(
$
entry
->
get_properties
(
)
as
$
property
)
{
$
property
->
register
(
'option'
)
;
}
}
}


public function get_setting( $key, $value ) {
		$property = null;

		foreach ( (array) $this->entries as $entry ) {
			if ( $property = $entry->get_property( $key ) ) {
				break;
			}
		}

		if ( is_null( $property ) ) {
			return $value;
		}

		$value = papi_get_option( $key );

		return $property->rest_prepare_value( $value );
	}

public function get_setting ( $ key , $ value ) { $ property = null ; foreach ( ( array ) $ this -> entries as $ entry ) { if ( $ property = $ entry -> get_property ( $ key ) ) { break ; } } if ( is_null ( $ property ) ) { return $ value ; } $ value = papi_get_option ( $ key ) ; return $ property -> rest_prepare_value ( $ value ) ; }

Get setting value for a property.

@param  string $key
@param  string $value

@return mixed


public function prepare_response( $response ) {
		$response = (array) $response;

		foreach ( $response as $key => $value ) {
			$setting = $this->get_setting( $key, $value );

			if ( $setting !== $value ) {
				$response[$key] = $setting;
			}
		}

		return $response;
	}

public function prepare_response ( $ response ) { $ response = ( array ) $ response ; foreach ( $ response as $ key => $ value ) { $ setting = $ this -> get_setting ( $ key , $ value ) ; if ( $ setting !== $ value ) { $ response [ $ key ] = $ setting ; } } return $ response ; }

Prepare settings response.

@param  WP_HTTP_Response $response

@return array


public function get_value() {
		$user = parent::get_value();

		if ( is_object( $user ) && isset( $user->ID ) ) {
			return $user->ID;
		}

		return 0;
	}

public function get_value ( ) { $ user = parent :: get_value ( ) ; if ( is_object ( $ user ) && isset ( $ user -> ID ) ) { return $ user -> ID ; } return 0 ; }


public function get_items() {
		$capabilities = papi_to_array( $this->get_setting( 'capabilities' ) );
		$users        = get_users();
		$items        = [];

		foreach ( $users as $user ) {
			$allcaps = $user->allcaps;

			if ( count( array_diff( $capabilities, array_keys( $allcaps ) ) ) === 0 ) {
				$items[$user->display_name] = $user->ID;
			}
		}

		ksort( $items );

		return $items;
	}

public function get_items ( ) { $ capabilities = papi_to_array ( $ this -> get_setting ( 'capabilities' ) ) ; $ users = get_users ( ) ; $ items = [ ] ; foreach ( $ users as $ user ) { $ allcaps = $ user -> allcaps ; if ( count ( array_diff ( $ capabilities , array_keys ( $ allcaps ) ) ) === 0 ) { $ items [ $ user -> display_name ] = $ user -> ID ; } } ksort ( $ items ) ; return $ items ; }

Get users as dropdown items.

@return array


protected function init() {
		// Fires the before init action.
		did_action( 'papi/before_init' ) || do_action( 'papi/before_init' );

		// Set up localisation.
		$this->load_textdomain();

		// Load all required files.
		$this->require_files();

		// Setup the container.
		$this->setup_container();

		// Fires the init action.
		did_action( 'papi/init' ) || do_action( 'papi/init' );
	}

protected
function
init
(
)
{
// Fires the before init action.
did_action
(
'papi/before_init'
)
||
do_action
(
'papi/before_init'
)
;
// Set up localisation.
$
this
->
load_textdomain
(
)
;
// Load all required files.
$
this
->
require_files
(
)
;
// Setup the container.
$
this
->
setup_container
(
)
;
// Fires the init action.
did_action
(
'papi/init'
)
||
do_action
(
'papi/init'
)
;
}


protected function load_textdomain() {
		$locale = function_exists( 'get_user_local' ) ? get_user_local() : get_locale();
		$locale = apply_filters( 'plugin_locale', $locale, 'papi' );

		load_textdomain( 'papi', WP_LANG_DIR . '/papi/papi-' . $locale . '.mo' );
		load_textdomain( 'papi', PAPI_PLUGIN_DIR . '../languages/papi-' . $locale . '.mo' );
	}

protected function load_textdomain ( ) { $ locale = function_exists ( 'get_user_local' ) ? get_user_local ( ) : get_locale ( ) ; $ locale = apply_filters ( 'plugin_locale' , $ locale , 'papi' ) ; load_textdomain ( 'papi' , WP_LANG_DIR . '/papi/papi-' . $ locale . '.mo' ) ; load_textdomain ( 'papi' , PAPI_PLUGIN_DIR . '../languages/papi-' . $ locale . '.mo' ) ; }

Load Localisation files.

Locales found in:
- WP_LANG_DIR/papi/papi-LOCALE.mo
- WP_CONTENT_DIR/[mu-]plugins/papi/languages/papi-LOCALE.mo


protected function require_files() {
		// Require the autoload class.
		require_once __DIR__ . '/core/class-papi-core-autoload.php';

		$lib_path     = __DIR__ . '/lib/';
		$lib_includes = [
			'core/cache.php',
			'core/conditional.php',
			'core/data.php',
			'core/deprecated.php',
			'core/meta.php',
			'core/store.php',
			'core/post.php',
			'core/io.php',
			'core/property.php',
			'core/slug.php',
			'core/tabs.php',
			'core/taxonomy.php',
			'core/template.php',
			'core/url.php',
			'core/utilities.php',
			'hooks/actions.php',
			'hooks/filters.php',
			'hooks/filters-page-type.php',
			'hooks/filters-taxonomy-type.php',
			'fields/page.php',
			'fields/option.php',
			'fields/taxonomy.php',
			'types/entry.php',
			'types/page.php',
			'types/option.php',
			'types/taxonomy.php'
		];

		// Require function files.
		foreach ( $lib_includes as $file ) {
			if ( file_exists( $lib_path . $file ) ) {
				require_once $lib_path . $file;
			}
		}

		unset( $file );

		// Require admin classes that should not be loaded by the autoload.
		require_once __DIR__ . '/admin/class-papi-admin.php';
		require_once __DIR__ . '/admin/class-papi-admin-ajax.php';
		require_once __DIR__ . '/admin/class-papi-admin-assets.php';
		require_once __DIR__ . '/admin/class-papi-admin-menu.php';

		// Require conditional rules that should not be loaded by the autoload.
		require_once __DIR__ . '/core/class-papi-core-conditional-rules.php';

		// Require REST API classes.
		require_once __DIR__ . '/rest-api/class-papi-rest-api.php';

		// Load Papi CLI class if WP CLI is used.
		if ( defined( 'WP_CLI' ) && WP_CLI ) {
			require_once __DIR__ . '/cli/class-papi-cli.php';
		}
	}


public static function deactivate() {
		// Remove Papi from plugins_loaded action.
		remove_action( 'plugins_loaded', 'papi' );

		// Load deactivate_plugins if it don't exists.
		if ( ! function_exists( 'deactivate_plugins' ) ) {
			include_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		deactivate_plugins( PAPI_PLUGIN_BASENAME );

		wp_die( esc_html__( 'WordPress 4.6 and higher required to run Papi! The plugin has now disabled itself.', 'papi' ) );

		// Remove instance.
		self::$instance = null;
	}

Deactivate Papi if the WordPress version is lower then 4.6.

Deactivate Papi if the WordPress version is lower then 4 . 6 .


public function is_string_items() {
		$items = $this->get_items();

		if ( empty( $items ) ) {
			return false;
		}

		$items = array_values( $items );

		return is_string( $items[0] );
	}

public function is_string_items ( ) { $ items = $ this -> get_items ( ) ; if ( empty ( $ items ) ) { return false ; } $ items = array_values ( $ items ) ; return is_string ( $ items [ 0 ] ) ; }

Determine if items are strings or not.

@return bool


protected function prepare_properties( $properties ) {
		$result = [];
		$value  = $this->get_value();
		$value  = is_array( $value ) ? $value : [];

		foreach ( $properties as $property ) {
			$render_property = clone $property->get_options();
			$value_slug      = $property->get_slug( true );

			if ( array_key_exists( $value_slug, $value ) ) {
				$render_property->value = $value[$value_slug];
			} else {
				$render_property->value = null;
			}

			$render_property->slug = $this->html_name( $property );

			$result[] = $render_property;
		}

		return $result;
	}

protected function prepare_properties ( $ properties ) { $ result = [ ] ; $ value = $ this -> get_value ( ) ; $ value = is_array ( $ value ) ? $ value : [ ] ; foreach ( $ properties as $ property ) { $ render_property = clone $ property -> get_options ( ) ; $ value_slug = $ property -> get_slug ( true ) ; if ( array_key_exists ( $ value_slug , $ value ) ) { $ render_property -> value = $ value [ $ value_slug ] ; } else { $ render_property -> value = null ; } $ render_property -> slug = $ this -> html_name ( $ property ) ; $ result [ ] = $ render_property ; } return $ result ; }

Prepare properties and set right slug and value.

@param  array $properties

@return array

Prepare properties and set right slug and value .


public function get_file( $value ) {
		$meta_key = $this->get_setting( 'meta_key' );

		if ( empty( $meta_key ) ) {
			if ( is_numeric( $value ) && intval( $value ) !== 0 ) {
				$post = get_post( $value );
			}
		} else if ( ! empty( $value ) ) {
			$args = [
				'fields'         => 'ids',
				'meta_key'       => $meta_key,
				'meta_value'     => $value,
				'posts_per_page' => 1,
				'post_type'      => 'attachment',
				'post_status'    => 'any'
			];

			$query = new WP_Query( $args );

			if ( ! empty( $query->posts ) ) {
				$post = get_post( $query->posts[0] );
			}
		}

		if ( empty( $post ) ) {
			return $value;
		}

		return $post->ID;
	}

public function get_file ( $ value ) { $ meta_key = $ this -> get_setting ( 'meta_key' ) ; if ( empty ( $ meta_key ) ) { if ( is_numeric ( $ value ) && intval ( $ value ) !== 0 ) { $ post = get_post ( $ value ) ; } } else if ( ! empty ( $ value ) ) { $ args = [ 'fields' => 'ids' , 'meta_key' => $ meta_key , 'meta_value' => $ value , 'posts_per_page' => 1 , 'post_type' => 'attachment' , 'post_status' => 'any' ] ; $ query = new WP_Query ( $ args ) ; if ( ! empty ( $ query -> posts ) ) { $ post = get_post ( $ query -> posts [ 0 ] ) ; } } if ( empty ( $ post ) ) { return $ value ; } return $ post -> ID ; }

Get file by id or meta value.

@param  mixed $value

@return int


protected function get_file_value( $value ) {
		$meta_key = $this->get_setting( 'meta_key' );

		if ( ! is_object( $value ) ) {
			return 0;
		}

		if ( empty( $meta_key ) ) {
			return $value->id;
		}

		if ( $value = get_post_meta( $value->id, $meta_key, true ) ) {
			return $value;
		}

		return 0;
	}

protected function get_file_value ( $ value ) { $ meta_key = $ this -> get_setting ( 'meta_key' ) ; if ( ! is_object ( $ value ) ) { return 0 ; } if ( empty ( $ meta_key ) ) { return $ value -> id ; } if ( $ value = get_post_meta ( $ value -> id , $ meta_key , true ) ) { return $ value ; } return 0 ; }

Get matching value based on key from a file.

@param  mixed $value

@return mixed

Get matching value based on key from a file .


public function update_value( $values, $slug, $post_id ) {
		if ( ! is_array( $values ) ) {
			$values = $this->get_file_value( (object) [
				'id' => $values
			] );

			if ( empty( $values ) ) {
				return;
			}

			return $values;
		}

		foreach ( $values as $index => $value ) {
			if ( ! is_numeric( $value ) ) {
				continue;
			}

			$values[$index] = $this->get_file_value( (object) [
				'id' => $value
			] );
		}

		return array_filter( $values );
	}

public function update_value ( $ values , $ slug , $ post_id ) { if ( ! is_array ( $ values ) ) { $ values = $ this -> get_file_value ( ( object ) [ 'id' => $ values ] ) ; if ( empty ( $ values ) ) { return ; } return $ values ; } foreach ( $ values as $ index => $ value ) { if ( ! is_numeric ( $ value ) ) { continue ; } $ values [ $ index ] = $ this -> get_file_value ( ( object ) [ 'id' => $ value ] ) ; } return array_filter ( $ values ) ; }

Save file with a meta value or id.

@param  mixed  $values
@param  string $slug
@param  int    $post_id

@return string


public function bind( $id, $value = null, $singleton = false ) {
		if ( is_string( $id ) && $this->is_singleton( $id ) ) {
			throw new Exception( sprintf( 'Identifier `%s` is a singleton and cannot be rebind', $id ) );
		}

		if ( is_object( $id ) && get_class( $id ) !== false ) {
			$value              = $id;
			$id                 = $this->get_class_prefix( get_class( $id ), false );
			$this->classes[$id] = true;
		}

		if ( $value instanceof Closure ) {
			$closure = $value;
		} else {
			$closure = $this->get_closure( $value, $singleton );
		}

		$this->values[$id] = compact( 'closure', 'singleton' );
		$this->keys[$id]   = true;

		return $value;
	}

Set a parameter or an object.

@param string $id
@param mixed  $value
@param bool   $singleton

@throws Exception when singleton cannot be rebind.

@return mixed


protected function call_closure( $closure, array $parameters = [] ) {
		if ( $closure instanceof Closure ) {
			$rc      = new ReflectionFunction( $closure );
			$args    = $rc->getParameters();
			$params  = $parameters;
			$classes = [
				$this->get_class_prefix( get_class( $this ) ),
				get_class( $this ),
				get_parent_class( $this )
			];

			foreach ( $args as $index => $arg ) {
				if ( $arg->getClass() === null ) {
					continue;
				}

				if ( in_array( $arg->getClass()->name, $classes, true ) ) {
					$parameters[$index] = $this;
				} else if ( $this->exists( $arg->getClass()->name ) ) {
					$parameters[$index] = $this->make( $arg->getClass()->name );
				}
			}

			if ( ! empty( $args ) && empty( $parameters ) ) {
				$parameters[0] = $this;
			}

			if ( count( $args ) > count( $parameters ) ) {
				$parameters = array_merge( $parameters, $params );
			}

			return $this->call_closure( call_user_func_array( $closure, $parameters ), $parameters );
		}

		return $closure;
	}

protected function call_closure ( $ closure , array $ parameters = [ ] ) { if ( $ closure instanceof Closure ) { $ rc = new ReflectionFunction ( $ closure ) ; $ args = $ rc -> getParameters ( ) ; $ params = $ parameters ; $ classes = [ $ this -> get_class_prefix ( get_class ( $ this ) ) , get_class ( $ this ) , get_parent_class ( $ this ) ] ; foreach ( $ args as $ index => $ arg ) { if ( $ arg -> getClass ( ) === null ) { continue ; } if ( in_array ( $ arg -> getClass ( ) -> name , $ classes , true ) ) { $ parameters [ $ index ] = $ this ; } else if ( $ this -> exists ( $ arg -> getClass ( ) -> name ) ) { $ parameters [ $ index ] = $ this -> make ( $ arg -> getClass ( ) -> name ) ; } } if ( ! empty ( $ args ) && empty ( $ parameters ) ) { $ parameters [ 0 ] = $ this ; } if ( count ( $ args ) > count ( $ parameters ) ) { $ parameters = array_merge ( $ parameters , $ params ) ; } return $ this -> call_closure ( call_user_func_array ( $ closure , $ parameters ) , $ parameters ) ; } return $ closure ; }

Call closure.

@param mixed $closure
@param array $parameters

@return Closure


protected function get_class_prefix( $id, $check = true ) {
		if ( strpos( $id, '\\' ) !== false && $id[0] !== '\\' ) {
			$class = '\\' . $id;

			if ( $check ) {
				return isset( $this->classes[$class] ) ? $class : $id;
			}

			return $class;
		}

		return $id;
	}

protected function get_class_prefix ( $ id , $ check = true ) { if ( strpos ( $ id , '\\' ) !== false && $ id [ 0 ] !== '\\' ) { $ class = '\\' . $ id ; if ( $ check ) { return isset ( $ this -> classes [ $ class ] ) ? $ class : $ id ; } return $ class ; } return $ id ; }

Get class prefix.

@param string $id
@param bool   $check

@return string


public function is_singleton( $id ) {
		if ( ! is_string( $id ) ) {
			throw new InvalidArgumentException( 'Invalid argument. Must be string.' );
		}

		if ( ! $this->exists( $id ) ) {
			return false;
		}

		$id = $this->get_class_prefix( $id );

		return $this->values[$id]['singleton'] === true;
	}

public
function
is_singleton
(
$
id
)
{
if
(
!
is_string
(
$
id
)
)
{
throw
new
InvalidArgumentException
(
'Invalid argument. Must be string.'
)
;
}
if
(
!
$
this
->
exists
(
$
id
)
)
{
return
false
;
}
$
id
=
$
this
->
get_class_prefix
(
$
id
)
;
return
$
this
->
values
[
$
id
]
[
'singleton'
]
===
true
;
}

Determine if a given type is a singleton or not.

@param string $id

@throws InvalidArgumentException if argument is not string.

@return bool

Determine if a given type is a singleton or not .


public function once( $key, $callback ) {
		if ( ! is_string( $key ) && ! is_callable( $callback ) ) {
			return;
		}

		if ( ! $this->exists( $key ) ) {
			$result = $callback();
			$this->singleton( $key, $result );
		}

		return $this->make( $key );
	}

public function once ( $ key , $ callback ) { if ( ! is_string ( $ key ) && ! is_callable ( $ callback ) ) { return ; } if ( ! $ this -> exists ( $ key ) ) { $ result = $ callback ( ) ; $ this -> singleton ( $ key , $ result ) ; } return $ this -> make ( $ key ) ; }

Add key and value to the container once.

@param  string $key
@param  mixed  $callback

@return mixed

Add key and value to the container once .


public function remove( $id ) {
		$id = $this->get_class_prefix( $id );
		unset( $this->keys[$id], $this->values[$id] );
	}

public function remove ( $ id ) { $ id = $ this -> get_class_prefix ( $ id ) ; unset ( $ this -> keys [ $ id ] , $ this -> values [ $ id ] ) ; }

Unset value by identifier.

@param string $id


protected function override_labels( Papi_Entry_Type $entry_type ) {
		global $wp_post_types, $wp_taxonomies;

		if ( $entry_type->get_type() === 'taxonomy' ) {
			$meta_type_value = papi_get_taxonomy();
		} else {
			$meta_type_value = papi_get_post_type();
		}

		if ( empty( $meta_type_value ) || ( ! isset( $wp_post_types[$meta_type_value] ) && ! isset( $wp_taxonomies[$meta_type_value] ) ) ) {
			return;
		}

		foreach ( $entry_type->get_labels() as $key => $value ) {
			if ( empty( $value ) ) {
				continue;
			}

			if ( $entry_type->get_type() === 'taxonomy' && isset( $wp_taxonomies[$meta_type_value]->labels->$key ) ) {
				$wp_taxonomies[$meta_type_value]->labels->$key = $value;
			} else if ( isset( $wp_post_types[$meta_type_value]->labels->$key ) ) {
				$wp_post_types[$meta_type_value]->labels->$key = $value;
			}
		}
	}

protected function override_labels ( Papi_Entry_Type $ entry_type ) { global $ wp_post_types , $ wp_taxonomies ; if ( $ entry_type -> get_type ( ) === 'taxonomy' ) { $ meta_type_value = papi_get_taxonomy ( ) ; } else { $ meta_type_value = papi_get_post_type ( ) ; } if ( empty ( $ meta_type_value ) || ( ! isset ( $ wp_post_types [ $ meta_type_value ] ) && ! isset ( $ wp_taxonomies [ $ meta_type_value ] ) ) ) { return ; } foreach ( $ entry_type -> get_labels ( ) as $ key => $ value ) { if ( empty ( $ value ) ) { continue ; } if ( $ entry_type -> get_type ( ) === 'taxonomy' && isset ( $ wp_taxonomies [ $ meta_type_value ] -> labels -> $ key ) ) { $ wp_taxonomies [ $ meta_type_value ] -> labels -> $ key = $ value ; } else if ( isset ( $ wp_post_types [ $ meta_type_value ] -> labels -> $ key ) ) { $ wp_post_types [ $ meta_type_value ] -> labels -> $ key = $ value ; } } }

Override labels with labels from the entry type.

@param Papi_Entry_Type $entry_type

Override labels with labels from the entry type .


public function page_items_menu() {
		$entry_types = papi_get_all_entry_types( [
			'mode'  => 'exclude',
			'types' => 'page'
		] );

		foreach ( $entry_types as $entry_type ) {
			if ( empty( $entry_type->get_menu() ) || empty( $entry_type->name ) ) {
				continue;
			}

			$slug = sprintf(
				'papi/%s/%s',
				$entry_type->get_type(),
				$entry_type->get_id()
			);

			add_submenu_page(
				$entry_type->get_menu(),
				$entry_type->name,
				$entry_type->name,
				$entry_type->capability,
				$slug,
				[$entry_type, 'render']
			);
		}
	}

public function page_items_menu ( ) { $ entry_types = papi_get_all_entry_types ( [ 'mode' => 'exclude' , 'types' => 'page' ] ) ; foreach ( $ entry_types as $ entry_type ) { if ( empty ( $ entry_type -> get_menu ( ) ) || empty ( $ entry_type -> name ) ) { continue ; } $ slug = sprintf ( 'papi/%s/%s' , $ entry_type -> get_type ( ) , $ entry_type -> get_id ( ) ) ; add_submenu_page ( $ entry_type -> get_menu ( ) , $ entry_type -> name , $ entry_type -> name , $ entry_type -> capability , $ slug , [ $ entry_type , 'render' ] ) ; } }

Page items menu.

This function will register all entry types
that has a fake post type. Like option types.


public function post_types_menu() {
		global $submenu;

		$post_types = papi_get_post_types();

		foreach ( $post_types as $post_type ) {
			if ( ! post_type_exists( $post_type ) ) {
				continue;
			}

			if ( $post_type === 'post' ) {
				$edit_url = 'edit.php';
			} else {
				$edit_url = 'edit.php?post_type=' . $post_type;
			}

			if ( ! isset( $submenu[$edit_url], $submenu[$edit_url][10], $submenu[$edit_url][10][2] ) ) {
				$post_type_object = get_post_type_object( $post_type );

				if ( $post_type_object->show_in_menu !== true ) {
					$submenu[$edit_url] = [
						10 => [
							__( 'Add New', 'papi' ),
							'edit_posts',
							'post-new.php'
						]
					];
				} else {
					continue;
				}
			}

			$only_page_type = papi_filter_settings_only_page_type( $post_type );
			$page_types     = papi_get_all_page_types( $post_type );
			$show_standard  = false;

			// Don't change menu item when no page types is found.
			if ( empty( $page_types ) ) {
				continue;
			}

			if ( count( $page_types ) === 1 && empty( $only_page_type ) ) {
				$show_standard  = papi_filter_settings_show_standard_page_type( $post_type );
				$only_page_type = $show_standard ? '' : $page_types[0]->get_id();
			}

			if ( ! empty( $only_page_type ) && ! $show_standard ) {
				$submenu[$edit_url][10][2] = papi_get_page_new_url(
					$only_page_type,
					false,
					$post_type,
					[
						'post_parent',
						'lang'
					]
				);
			} else {
				$page  = 'papi-add-new-page,' . $post_type;
				$start = strpos( $edit_url, 'post_type' ) === false ? '?' : '&';

				$submenu[$edit_url][10][2] = sprintf(
					'%s%spage=%s',
					$edit_url,
					$start,
					$page
				);

				// Add menu item.
				add_menu_page(
					__( 'Add New', 'papi' ),
					__( 'Add New', 'papi' ),
					'read',
					$page,
					[$this, 'render_view']
				);

				// Remove the menu item so it's hidden.
				remove_menu_page( $page );
			}
		}
	}


public function render_view() {
		if ( strpos( papi_get_qs( 'page' ), 'papi' ) !== false ) {
			$page = str_replace( 'papi-', '', papi_get_qs( 'page' ) );
			$res  = preg_replace( '/\,.*/', '', $page );

			if ( is_string( $res ) ) {
				$page_view = $res;
			}
		}

		if ( ! isset( $page_view ) ) {
			$page_view = null;
		}

		if ( ! is_null( $page_view ) ) {
			$view = new Papi_Admin_View;
			$view->render( $page_view );
		} else {
			echo '
Papi - 404
';
		}
	}

public
function
render_view
(
)
{
if
(
strpos
(
papi_get_qs
(
'page'
)
,
'papi'
)
!==
false
)
{
$
page
=
str_replace
(
'papi-'
,
''
,
papi_get_qs
(
'page'
)
)
;
$
res
=
preg_replace
(
'/\,.*/'
,
''
,
$
page
)
;
if
(
is_string
(
$
res
)
)
{
$
page_view
=
$
res
;
}
}
if
(
!
isset
(
$
page_view
)
)
{
$
page_view
=
;
}
if
(
!
is_null
(
$
page_view
)
)
{
$
view
=
new
Papi_Admin_View
;
$
view
->
render
(
$
page_view
)
;
}
else
{
echo
'
Papi - 404
'
;
}
}

Menu callback that loads right view depending on what the `page` query string says.

Menu callback that loads right view depending on what the page query string says .


public function autoload( $class ) {
		$class = strtolower( $class );
		$file  = 'class-' . str_replace( '_', '-', strtolower( $class ) ) . '.php';
		$path  = PAPI_PLUGIN_DIR;

		if ( strpos( $class, 'papi_admin' ) === 0 ) {
			$path .= 'admin/';
		} else if ( strpos( $class, 'papi_core_' ) === 0 ) {
			$path .= 'core/';
		} else if ( strpos( $class, 'papi_cli_' ) === 0 ) {
			$path .= 'cli/';
		} else if ( preg_match( '/^papi\_\w+\_store$/', $class ) ) {
			$path .= 'stores/';
		} else if ( strpos( $class, 'papi_property' ) === 0 ) {
			$path .= 'properties/';
		} else if ( strpos( $class, 'papi_query' ) === 0 ) {
			$path .= 'query/';
		} else if ( preg_match( '/^papi\_\w+\_type/', $class ) ) {
			$path .= 'types/';
		}

		if ( is_readable( $path . $file ) ) {
			require_once $path . $file;
		}
	}

public function autoload ( $ class ) { $ class = strtolower ( $ class ) ; $ file = 'class-' . str_replace ( '_' , '-' , strtolower ( $ class ) ) . '.php' ; $ path = PAPI_PLUGIN_DIR ; if ( strpos ( $ class , 'papi_admin' ) === 0 ) { $ path .= 'admin/' ; } else if ( strpos ( $ class , 'papi_core_' ) === 0 ) { $ path .= 'core/' ; } else if ( strpos ( $ class , 'papi_cli_' ) === 0 ) { $ path .= 'cli/' ; } else if ( preg_match ( '/^papi\_\w+\_store$/' , $ class ) ) { $ path .= 'stores/' ; } else if ( strpos ( $ class , 'papi_property' ) === 0 ) { $ path .= 'properties/' ; } else if ( strpos ( $ class , 'papi_query' ) === 0 ) { $ path .= 'query/' ; } else if ( preg_match ( '/^papi\_\w+\_type/' , $ class ) ) { $ path .= 'types/' ; } if ( is_readable ( $ path . $ file ) ) { require_once $ path . $ file ; } }

Autoload Papi classes.

@codeCoverageIgnore

@param string $class


public function get_items() {
		global $wp_registered_sidebars;
		$items = [];

		foreach ( $wp_registered_sidebars as $item ) {
			$items[$item['name']] = $item['id'];
		}

		ksort( $items );

		return $items;
	}

public function get_items ( ) { global $ wp_registered_sidebars ; $ items = [ ] ; foreach ( $ wp_registered_sidebars as $ item ) { $ items [ $ item [ 'name' ] ] = $ item [ 'id' ] ; } ksort ( $ items ) ; return $ items ; }

Get registered sidebars as dropdown items.

@return array

Get registered sidebars as dropdown items .


protected function get_labels() {
		$results = [];

		foreach ( $this->get_post_types() as $post_type ) {
			if ( post_type_exists( $post_type ) ) {
				$post_type_object    = get_post_type_object( $post_type );
				$results[$post_type] = $post_type_object->labels->menu_name;
			}
		}

		return $results;
	}

protected function get_labels ( ) { $ results = [ ] ; foreach ( $ this -> get_post_types ( ) as $ post_type ) { if ( post_type_exists ( $ post_type ) ) { $ post_type_object = get_post_type_object ( $ post_type ) ; $ results [ $ post_type ] = $ post_type_object -> labels -> menu_name ; } } return $ results ; }

Get labels from post types.

@return array


public function parse_args( array $args ) {
		$args = array_merge( $this->default_args, $args );

		// Since a page type has defined post types we should use them.
		// With a fallback on `post_type` args or `any` value.
		if ( $this->type === 'post' ) {
			$args = $this->parse_post_args( $args );
		} else if ( $this->type === 'term' ) {
			$args = $this->parse_term_args( $args );
		}

		$this->args = $args;
	}

Parse query arguments.

@param  array $args


protected function parse_post_args( array $args ) {
		if ( isset( $args['page_type'] ) ) {
			$args['entry_type'] = $args['page_type'];

			unset( $args['page_type'] );
		}

		$entry_type = papi_get_entry_type_by_id( $args['entry_type'] );

		if ( $entry_type instanceof Papi_Page_Type ) {
			$args['post_type'] = papi_to_array( $entry_type->post_type );
		} else {
			$args['post_type'] = isset( $args['post_type'] ) ? $args['post_type'] : '';
		}

		return $args;
	}

protected function parse_post_args ( array $ args ) { if ( isset ( $ args [ 'page_type' ] ) ) { $ args [ 'entry_type' ] = $ args [ 'page_type' ] ; unset ( $ args [ 'page_type' ] ) ; } $ entry_type = papi_get_entry_type_by_id ( $ args [ 'entry_type' ] ) ; if ( $ entry_type instanceof Papi_Page_Type ) { $ args [ 'post_type' ] = papi_to_array ( $ entry_type -> post_type ) ; } else { $ args [ 'post_type' ] = isset ( $ args [ 'post_type' ] ) ? $ args [ 'post_type' ] : '' ; } return $ args ; }

Parse post query arguments.

@param  array $args

@return array


protected function parse_term_args( array $args ) {
		if ( isset( $args['taxonomy_type'] ) ) {
			$args['entry_type'] = $args['taxonomy_type'];

			unset( $args['taxonomy_type'] );
		}

		$entry_type = papi_get_entry_type_by_id( $args['entry_type'] );

		if ( $entry_type instanceof Papi_Taxonomy_Type ) {
			$args['taxonomy'] = papi_to_array( $entry_type->taxonomy );
		} else {
			$args['taxonomy'] = isset( $args['taxonomy'] ) ? $args['taxonomy'] : '';
		}

		return $args;
	}

protected function parse_term_args ( array $ args ) { if ( isset ( $ args [ 'taxonomy_type' ] ) ) { $ args [ 'entry_type' ] = $ args [ 'taxonomy_type' ] ; unset ( $ args [ 'taxonomy_type' ] ) ; } $ entry_type = papi_get_entry_type_by_id ( $ args [ 'entry_type' ] ) ; if ( $ entry_type instanceof Papi_Taxonomy_Type ) { $ args [ 'taxonomy' ] = papi_to_array ( $ entry_type -> taxonomy ) ; } else { $ args [ 'taxonomy' ] = isset ( $ args [ 'taxonomy' ] ) ? $ args [ 'taxonomy' ] : '' ; } return $ args ; }

Parse term query arguments.

@param  array $args

@return array


public function get_query_args() {
		$args = $this->args;

		if ( empty( $args['meta_query'] ) ) {
			// Add new meta key/value if `meta_key` or `meta_value` is empty.
			if ( empty( $args['meta_key'] ) || empty( $args['meta_value'] ) ) {
				$args['meta_key']   = papi_get_page_type_key();
				$args['meta_value'] = $args['entry_type'];
			} else if ( papi_entry_type_exists( $args['entry_type'] ) ) {
				$item = [
					'key'   => $args['meta_key'],
					'value' => $args['meta_value']
				];

				// Add `meta_compare` if set.
				if ( isset( $args['meta_compare'] ) ) {
					$item['compare'] = $args['meta_compare'];

					unset( $args['meta_compare'] );
				}

				// Add new meta query item.
				$args['meta_query'][] = $item;

				// Add Papi entry/page type meta query.
				$args['meta_query'][] = [
					'key'   => papi_get_page_type_key(),
					'value' => $args['entry_type']
				];

				// Add meta query relation when two query items.
				if ( isset( $args['relation'] ) ) {
					$args['meta_query']['relation'] = $args['relation'];
				} else {
					$args['meta_query']['relation'] = 'AND';
				}

				unset( $args['meta_key'] );
				unset( $args['meta_value'] );
			}
		} else if ( papi_entry_type_exists( $args['entry_type'] ) ) {
			// Add Papi entry/page type meta query.
			$args['meta_query'][] = [
				'key'   => papi_get_page_type_key(),
				'value' => $args['entry_type']
			];

			// Add meta query relation if not set.
			if ( ! isset( $args['meta_query']['relation'] ) ) {
				$args['meta_query']['relation'] = 'AND';
			}
		}

		// Since the real query classes don't support
		// custom arguments the should be deleted.
		foreach ( array_keys( $this->default_args ) as $key ) {
			if ( isset( $args[$key] ) ) {
				unset( $args[$key] );
			}
		}

		return $args;
	}

Get real query arguments without Papi Query specific arguments.

@return array

Get real query arguments without Papi Query specific arguments .


public function get_result() {
		if ( ! method_exists( $this->query, 'query' ) ) {
			return [];
		}

		$this->parse_args( $this->args );

		return $this->query->query( $this->get_query_args() );
	}

public function get_result ( ) { if ( ! method_exists ( $ this -> query , 'query' ) ) { return [ ] ; } $ this -> parse_args ( $ this -> args ) ; return $ this -> query -> query ( $ this -> get_query_args ( ) ) ; }

Get result.

Works for all query types.

@return array


public function add_help_tabs() {
		$help   = $this->help();
		$screen = get_current_screen();

		// No screen available.
		if ( $screen instanceof WP_Screen === false ) {
			return;
		}

		// Clean up all existing tabs.
		if ( ! $this->show_help_tabs || ! empty( $help ) ) {
			$screen->remove_help_tabs();
		}

		// No new help tabs available.
		if ( empty( $help ) ) {
			return;
		}

		// Add help sidebar content. By default it will be disabled
		// since `help_sidebar` method returns false.
		$help_sidebar = $this->help_sidebar();
		$help_sidebar = papi_maybe_get_callable_value( $help_sidebar );
		$screen->set_help_sidebar( wpautop( $help_sidebar ) );

		foreach ( $help as $key => $value ) {
			$args = [
				'id'    => papi_html_name( $key ),
				'title' => $key
			];

			if ( is_callable( $value ) ) {
				$args['callback'] = function () use ( $value ) {
					return wpautop( $value() );
				};
			} else {
				$args['content'] = wpautop( $value );
			}

			$screen->add_help_tab( $args );
		}
	}


protected function box( $file_or_options = [], $properties = [] ) {
		if ( ! is_string( $file_or_options ) && ! is_array( $file_or_options ) && ! is_object( $file_or_options ) ) {
			return;
		}

		list( $options, $properties ) = papi_get_options_and_properties(
			$file_or_options,
			$properties,
			true
		);

		// Check so we have a post the to add the box to.
		// @codeCoverageIgnoreStart
		if ( ! $this->load_boxes ) {
			return;
		}
		// @codeCoverageIgnoreEnd

		if ( is_callable( $properties ) ) {
			$properties = call_user_func( $properties );
		}

		// Check and convert all non properties objects to properties objects.
		$properties = $this->convert_properties( $properties );

		// Create a core box instance and add it to the boxes array.
		array_push( $this->boxes, new Papi_Core_Box( $options, $properties ) );
	}

Add new meta box with properties.

@param mixed $file_or_options
@param array $properties


protected function call_parent_register() {
		$parent_class = get_parent_class( $this );

		if ( ! method_exists( $parent_class, 'register' ) ) {
			return;
		}

		$rc = new ReflectionClass( $parent_class );

		// Bail if not instantiable.
		if ( ! $rc->isinstantiable() ) {
			return;
		}

		$parent = $rc->newInstance();
		$parent->register();
		$this->boxes = $parent->get_boxes();
	}

protected
function
call_parent_register
(
)
{
$
parent_class
=
get_parent_class
(
$
this
)
;
if
(
!
method_exists
(
$
parent_class
,
'register'
)
)
{
return
;
}
$
rc
=
new
ReflectionClass
(
$
parent_class
)
;
// Bail if not instantiable.
if
(
!
$
rc
->
isinstantiable
(
)
)
{
return
;
}
$
parent
=
$
rc
->
newInstance
(
)
;
$
parent
->
register
(
)
;
$
this
->
boxes
=
$
parent
->
get_boxes
(
)
;
}

Call parent register if it exists
to collect boxes on the parent entry type.

Call parent register if it exists to collect boxes on the parent entry type .


protected function convert_properties( $properties ) {
		if ( is_array( $properties ) ) {
			if ( isset( $properties['type'] ) ) {
				$properties = [$properties];
			} else if ( isset( $properties[0] ) && $properties[0] instanceof Papi_Core_Tab ) {
				foreach ( $properties as $items ) {
					$items->properties = array_map( 'papi_get_property_type', $items->properties );
				}

				return $properties;
			}
		}

		if ( is_object( $properties ) ) {
			$properties = papi_get_property_type( $properties );
		}

		if ( papi_is_property( $properties ) ) {
			$properties = [$properties];
		}

		$properties = is_array( $properties ) ? $properties : [];
		$properties = array_map( 'papi_get_property_type', $properties );

		return array_filter( $properties, 'papi_is_property' );
	}

protected function convert_properties ( $ properties ) { if ( is_array ( $ properties ) ) { if ( isset ( $ properties [ 'type' ] ) ) { $ properties = [ $ properties ] ; } else if ( isset ( $ properties [ 0 ] ) && $ properties [ 0 ] instanceof Papi_Core_Tab ) { foreach ( $ properties as $ items ) { $ items -> properties = array_map ( 'papi_get_property_type' , $ items -> properties ) ; } return $ properties ; } } if ( is_object ( $ properties ) ) { $ properties = papi_get_property_type ( $ properties ) ; } if ( papi_is_property ( $ properties ) ) { $ properties = [ $ properties ] ; } $ properties = is_array ( $ properties ) ? $ properties : [ ] ; $ properties = array_map ( 'papi_get_property_type' , $ properties ) ; return array_filter ( $ properties , 'papi_is_property' ) ; }

Convert properties to properties objects.

@param  array|object $properties

@return array

Convert properties to properties objects .


public function get_body_classes() {
		$arr = $this->body_classes();
		$arr = is_string( $arr ) ? [$arr] : $arr;
		$arr = is_array( $arr ) ? $arr : [];

		return array_merge( $arr, [] );
	}

public function get_body_classes ( ) { $ arr = $ this -> body_classes ( ) ; $ arr = is_string ( $ arr ) ? [ $ arr ] : $ arr ; $ arr = is_array ( $ arr ) ? $ arr : [ ] ; return array_merge ( $ arr , [ ] ) ; }

Get admin body css classes.

Use `body_classes` method to add custom admin body classes.

@return array


public function get_boxes() {
		if ( empty( $this->boxes ) && $this->load_boxes === false ) {
			if ( ! method_exists( $this, 'register' ) ) {
				return [];
			}

			$this->load_boxes = true;

			$this->call_parent_register();
			$this->register();
		}

		// Merge boxes, e.g a parent box with a child box.
		$this->boxes = $this->merge_boxes( $this->boxes );

		/**
		 * Modify boxes array.
		 *
		 * @param array  $boxes
		 * @param string $id
		 */
		$this->boxes = apply_filters( 'papi/get_boxes', $this->boxes, $this->get_id() );
		$this->boxes = is_array( $this->boxes ) ? $this->boxes : [];

		// Go through all boxes and only add boxes
		// that is a array and remove boxes that isn't
		// a instance of core box class.
		foreach ( $this->boxes as $index => $box ) {
			if ( is_array( $box ) ) {
				if ( is_string( $index ) ) {
					$box['title'] = $index;
				}

				$this->box( $box );

				unset( $this->boxes[$index] );
				continue;
			}

			// Remove boxes that isn't a instanceof core box class.
			if ( $box instanceof Papi_Core_Box === false ) {
				unset( $this->boxes[$index] );
				continue;
			}

			// Remove box if site id isn't zero and isn't the current blog id.
			if ( $box->site_id !== 0 && $box->site_id !== get_current_blog_id() ) {
				unset( $this->boxes[$index] );
				continue;
			}
		}

		return papi_sort_order( array_reverse( $this->boxes ) );
	}

Get boxes from the page type.

@return array


public function get_property( $slug, $child_slug = '' ) {
		$boxes = $this->get_boxes();
		$parts = preg_match( '/\[\d+\]/', $slug ) ? preg_split( '/\[\d+\]/', $slug ) : explode( '[', $slug );
		$parts = array_map( function ( $part ) {
			return preg_replace( '/(\[|\])/', '', $part );
		}, $parts );

		if ( count( $parts ) > 1 ) {
			$property = null;

			for ( $i = 0, $l = count( $parts ); $i < $l; $i++ ) {
				$child    = isset( $parts[$i + 1] ) ? $parts[$i + 1] : '';
				$property = $this->get_property( $parts[$i], $child );

				if ( isset( $parts[$i + 1] ) ) {
					$i++;
				}
			}

			/**
			 * Modify property.
			 *
			 * @param  Papi_Core_Property $property
			 */
			return apply_filters( 'papi/get_property', $property );
		}

		foreach ( $boxes as $box ) {
			foreach ( $box->properties as $property ) {
				$property = papi_get_property_type( $property );

				if ( papi_is_property( $property ) && $property->match_slug( $slug ) ) {
					if ( empty( $child_slug ) ) {
						/**
						 * Modify property.
						 *
						 * @param  Papi_Core_Property $property
						 */
						return apply_filters( 'papi/get_property', $property );
					}

					$property = $property->get_child_property( $child_slug );

					if ( papi_is_property( $property ) ) {
						/**
						 * Modify property.
						 *
						 * @param  Papi_Core_Property $property
						 */
						return apply_filters( 'papi/get_property', $property );
					}
				}
			}
		}
	}

Get property from entry type.

@param  string $slug
@param  string $child_slug

@return Papi_Property


public function get_properties() {
		$boxes = $this->get_boxes();
		$list  = [];

		foreach ( $boxes as $box ) {
			foreach ( $box->properties as $property ) {
				$list[] = $property;
			}
		}

		return $list;
	}

public function get_properties ( ) { $ boxes = $ this -> get_boxes ( ) ; $ list = [ ] ; foreach ( $ boxes as $ box ) { foreach ( $ box -> properties as $ property ) { $ list [ ] = $ property ; } } return $ list ; }


protected function merge_boxes( array $boxes ) {
		$result = [];

		foreach ( $boxes as $box ) {
			if ( ! isset( $result[$box->id] ) ) {
				$result[$box->id] = $box;
				continue;
			}

			foreach ( $box->properties as $property ) {
				$result[$box->id]->properties[] = $property;
			}

			$result[$box->id]->properties = array_unique( $result[$box->id]->properties );
		}

		return array_values( $result );
	}

protected function merge_boxes ( array $ boxes ) { $ result = [ ] ; foreach ( $ boxes as $ box ) { if ( ! isset ( $ result [ $ box -> id ] ) ) { $ result [ $ box -> id ] = $ box ; continue ; } foreach ( $ box -> properties as $ property ) { $ result [ $ box -> id ] -> properties [ ] = $ property ; } $ result [ $ box -> id ] -> properties = array_unique ( $ result [ $ box -> id ] -> properties ) ; } return array_values ( $ result ) ; }

Merge boxes with same title.

@param  array $boxes

@return array


public function setup() {
		add_action( 'in_admin_header', [$this, 'add_help_tabs'] );
		add_filter( 'screen_options_show_screen', function () {
			return $this->show_screen_options;
		} );

		// @codeCoverageIgnoreStart
		if ( ! method_exists( $this, 'register' ) ) {
			return;
		}
		// @codeCoverageIgnoreEnd

		$this->register();

		foreach ( $this->get_boxes() as $box ) {
			new Papi_Admin_Meta_Box( $box );
		}
	}

public
function
setup
(
)
{
add_action
(
'in_admin_header'
,
[
$
this
,
'add_help_tabs'
]
)
;
add_filter
(
'screen_options_show_screen'
,
function
(
)
{
return
$
this
->
show_screen_options
;
}
)
;
// @codeCoverageIgnoreStart
if
(
!
method_exists
(
$
this
,
'register'
)
)
{
return
;
}
// @codeCoverageIgnoreEnd
$
this
->
register
(
)
;
foreach
(
$
this
->
get_boxes
(
)
as
$
box
)
{
new
Papi_Admin_Meta_Box
(
$
box
)
;
}
}


protected function tab( $file_or_options = [], $properties = [] ) {
		if ( ! is_string( $file_or_options ) && ! is_array( $file_or_options ) ) {
			return;
		}

		return papi_tab( $file_or_options, $properties );
	}

protected function tab ( $ file_or_options = [ ] , $ properties = [ ] ) { if ( ! is_string ( $ file_or_options ) && ! is_array ( $ file_or_options ) ) { return ; } return papi_tab ( $ file_or_options , $ properties ) ; }

Add a new tab.

@param  mixed $file_or_options
@param  array $properties

@return null|Papi_Core_Tab


public function load_value( $value, $slug, $post_id ) {
		if ( is_array( $value ) || is_object( $value ) ) {
			$values = $value;
		} else {
			$values = $this->link_fields;

			foreach ( $values as $index => $key ) {
				$values[$key] = papi_data_get(
					$post_id,
					sprintf( '%s_%s', $slug, $key ),
					$this->get_meta_type()
				);
				unset( $values[$index] );
			}
		}

		return (object) $this->prepare_link_array( $values, $slug );
	}

public function load_value ( $ value , $ slug , $ post_id ) { if ( is_array ( $ value ) || is_object ( $ value ) ) { $ values = $ value ; } else { $ values = $ this -> link_fields ; foreach ( $ values as $ index => $ key ) { $ values [ $ key ] = papi_data_get ( $ post_id , sprintf ( '%s_%s' , $ slug , $ key ) , $ this -> get_meta_type ( ) ) ; unset ( $ values [ $ index ] ) ; } } return ( object ) $ this -> prepare_link_array ( $ values , $ slug ) ; }

Load value from database.

@param  mixed  $value
@param  string $slug
@param  int    $post_id

@return array


protected function prepare_link_array( $link, $slug ) {
		$array  = is_array( $link );
		$values = (array) $link;

		foreach ( $values as $key => $val ) {
			unset( $values[$key] );
			$key = preg_replace( '/^' . $slug . '\_/', '', $key );
			$values[$key] = $val;
		}

		$link = (object) $values;

		// Don't continue without a url.
		if ( ! isset( $link->url ) || empty( $link->url ) ) {
			return $array ? (array) $link : $link;
		}

		// Don't overwrite existing post id.
		if ( ! isset( $link->post_id ) || empty( $link->post_id ) ) {
			$link->post_id = url_to_postid( $link->url );
		}

		// If empty target set `_self` as default target.
		if ( empty( $link->target ) ) {
			$link->target = '_self';
		}

		// Remove slug if it exists.
		if ( isset( $link->$slug ) && is_numeric( $link->$slug ) ) {
			unset( $link->$slug );
		}

		return $array ? (array) $link : $link;
	}

Prepare link array with post id. If it gets a post id
bigger then zero it will use the permalink as url.

@param  array|object $link
@param  string       $slug

@return array|object

Prepare link array with post id . If it gets a post id bigger then zero it will use the permalink as url .


public function update_value( $values, $slug, $post_id ) {
		if ( is_object( $values ) ) {
			$values = (array) $values;
		}

		if ( ! isset( $values['url'] ) ) {
			$values = $this->link_fields;

			foreach ( $values as $index => $key ) {
				$values[sprintf( '%s_%s', $slug, $key )] = '';
				unset( $values[$index] );
			}

			// Delete the required field.
			$values[$slug] = '';

			return $values;
		}

		// If a url exists we can continue making the meta fields
		// that should be saved.
		$values = $this->prepare_link_array( $values, $slug );

		foreach ( $values as $key => $val ) {
			$values[sprintf( '%s_%s', $slug, $key )] = $val;
			unset( $values[$key] );
		}

		// Required field so Papi can load a value from the
		// original property slug.
		$values[$slug] = 1;

		return $values;
	}

Prepare value for the database.

@param  mixed  $values
@param  string $slug
@param  int    $post_id

@return array


public function allowed() {
		$args = func_get_args();

		if ( empty( $args ) ) {
			return parent::allowed();
		}

		return isset( $args[0] ) && in_array( $args[0], $this->taxonomy, true );
	}

public function allowed ( ) { $ args = func_get_args ( ) ; if ( empty ( $ args ) ) { return parent :: allowed ( ) ; } return isset ( $ args [ 0 ] ) && in_array ( $ args [ 0 ] , $ this -> taxonomy , true ) ; }

Determine if the taxonomy type is allowed by taxonomy type.

@return bool

Determine if the taxonomy type is allowed by taxonomy type .


public function edit_form() {
		?>

			<?php wp_editor( '', 'papiHiddenEditor' ); ?>

				<?php
				foreach ( $this->boxes as $box ) {
					do_meta_boxes(
						$box->id,
						'normal',
						null
					);
				}
				?>

		<?php
	}

?>
		<div id="papi-hidden-editor" class="hide-if-js">
			<?php


public function get_post( WP_Post $post ) {
		if ( ! ( $page_type = papi_get_entry_type_by_meta_id( $post->ID ) ) ) {
			return $post;
		}

		// Register all properties fields with register meta.
		foreach ( $page_type->get_properties() as $property ) {
			$property->register();
		}

		// Add filter to prepare the response for a post type.
		add_filter( 'rest_prepare_' . $post->post_type, [$this, 'prepare_response'] );

		return $post;
	}

Filter the post.

Register all properties with `register_meta` and prepare response filter.

@param  WP_Post $post

@return WP_Post


public function prepare_response( $response ) {
		if ( ! isset( $response->data['meta'] ) ) {
			return $response;
		}

		foreach ( $response->data['meta'] as $key => $value ) {
			$response->data['meta'][$key] = papi_get_field( $key, $value, 'post' );
		}

		return $response;
	}

public function prepare_response ( $ response ) { if ( ! isset ( $ response -> data [ 'meta' ] ) ) { return $ response ; } foreach ( $ response -> data [ 'meta' ] as $ key => $ value ) { $ response -> data [ 'meta' ] [ $ key ] = papi_get_field ( $ key , $ value , 'post' ) ; } return $ response ; }

Prepare response.

@param  WP_REST_Response $response

@return WP_REST_Response


public function setup_fields() {
		if ( ! function_exists( 'register_rest_field' ) ) {
			return;
		}

		$post_types = papi_get_post_types();

		foreach ( $post_types as $post_type ) {
			register_rest_field( $post_type, 'page_type', [
				'get_callback' => [$this, 'get_page_type']
			] );
		}
	}

public function setup_fields ( ) { if ( ! function_exists ( 'register_rest_field' ) ) { return ; } $ post_types = papi_get_post_types ( ) ; foreach ( $ post_types as $ post_type ) { register_rest_field ( $ post_type , 'page_type' , [ 'get_callback' => [ $ this , 'get_page_type' ] ] ) ; } }


protected function get_format_args( $assoc_args ) {
		$format_args = [
			'fields' => $this->get_default_format_fields(),
			'field'  => null,
			'format' => 'table',
		];

		if ( isset( $assoc_args['fields'] ) ) {
			$format_args['fields'] = $assoc_args['fields'];
		}

		if ( isset( $assoc_args['field'] ) ) {
			$format_args['field'] = $assoc_args['field'];
		}

		if ( ! empty( $assoc_args['format'] ) && in_array( $assoc_args['format'], ['count', 'ids', 'table', 'csv', 'json'], true ) ) {
			$format_args['format'] = $assoc_args['format'];
		}

		return $format_args;
	}

protected function get_format_args ( $ assoc_args ) { $ format_args = [ 'fields' => $ this -> get_default_format_fields ( ) , 'field' => null , 'format' => 'table' , ] ; if ( isset ( $ assoc_args [ 'fields' ] ) ) { $ format_args [ 'fields' ] = $ assoc_args [ 'fields' ] ; } if ( isset ( $ assoc_args [ 'field' ] ) ) { $ format_args [ 'field' ] = $ assoc_args [ 'field' ] ; } if ( ! empty ( $ assoc_args [ 'format' ] ) && in_array ( $ assoc_args [ 'format' ] , [ 'count' , 'ids' , 'table' , 'csv' , 'json' ] , true ) ) { $ format_args [ 'format' ] = $ assoc_args [ 'format' ] ; } return $ format_args ; }

Get format args that will be passed into CLI Formatter.

@param  array $assoc_args Associative args from CLI

@return array Formatter args

Get format args that will be passed into CLI Formatter .


public function render( $file ) {
		if ( ! empty( $file ) && $this->exists( $file ) ) {
			require $this->file( $file );
		}
	}

public function render ( $ file ) { if ( ! empty ( $ file ) && $ this -> exists ( $ file ) ) { require $ this -> file ( $ file ) ; } }

Render file.

@param  string $file

@return string


public function get_option( $key ) {
		return isset( $this->options[$key] ) ? $this->options[$key] : null;
	}

public function get_option ( $ key ) { return isset ( $ this -> options [ $ key ] ) ? $ this -> options [ $ key ] : null ; }

Get box option.

@param  string $key

@return mixed


protected function convert_prop( $value, Papi_Core_Conditional_Rule $rule ) {
		$meta_id    = papi_get_meta_id();
		$meta_type  = papi_get_meta_type();
		$entry_type = papi_get_entry_type_by_meta_id( $meta_id, $meta_type );

		if ( ! papi_is_empty( $value ) && $entry_type instanceof Papi_Entry_Type !== false ) {
			$property = $entry_type->get_property( $rule->slug );

			if ( papi_is_property( $property ) ) {
				$prop_value = $property->format_value(
					$value,
					$property->slug,
					$meta_id
				);

				$prop_value = papi_filter_format_value(
					$property->type,
					$prop_value,
					$property->slug,
					$meta_id,
					$meta_type
				);

				$prop_value = $this->get_deep_value(
					$rule->slug,
					$prop_value
				);

				if ( gettype( $prop_value ) === gettype( $rule->value ) ) {
					return $prop_value;
				}
			}

			return $value;
		}

		return $value;
	}

protected function convert_prop ( $ value , Papi_Core_Conditional_Rule $ rule ) { $ meta_id = papi_get_meta_id ( ) ; $ meta_type = papi_get_meta_type ( ) ; $ entry_type = papi_get_entry_type_by_meta_id ( $ meta_id , $ meta_type ) ; if ( ! papi_is_empty ( $ value ) && $ entry_type instanceof Papi_Entry_Type !== false ) { $ property = $ entry_type -> get_property ( $ rule -> slug ) ; if ( papi_is_property ( $ property ) ) { $ prop_value = $ property -> format_value ( $ value , $ property -> slug , $ meta_id ) ; $ prop_value = papi_filter_format_value ( $ property -> type , $ prop_value , $ property -> slug , $ meta_id , $ meta_type ) ; $ prop_value = $ this -> get_deep_value ( $ rule -> slug , $ prop_value ) ; if ( gettype ( $ prop_value ) === gettype ( $ rule -> value ) ) { return $ prop_value ; } } return $ value ; } return $ value ; }

Convert value from a property.

@param  mixed $value
@param  Papi_Core_Conditional_Rule $rule

@return mixed


protected function get_converted_value( Papi_Core_Conditional_Rule $rule ) {
		$value = $this->get_value( $rule );

		// Convert numeric values.
		if ( is_numeric( $value ) && is_numeric( $rule->value ) ) {
			return [
				$this->convert_number( $value ),
				$this->convert_number( $rule->value )
			];
		}

		// Convert bool value if it a string bool or return value.
		$value       = $this->convert_bool( $value );
		$rule->value = $this->convert_bool( $rule->value );

		// Try to convert the property to the same value as the rule value.
		return [
			$this->convert_prop( $value, $rule ),
			$rule->value
		];
	}

Get converted value.

@param  Papi_Core_Conditional_Rule $rule

@return array


protected function get_deep_value( $slug, $value ) {
		$slugs = explode( '.', $slug );
		array_shift( $slugs );
		return papi_field_value( $slugs, $value, $value );
	}

protected function get_deep_value ( $ slug , $ value ) { $ slugs = explode ( '.' , $ slug ) ; array_shift ( $ slugs ) ; return papi_field_value ( $ slugs , $ value , $ value ) ; }

Get deep value.

@param  string $slug
@param  mixed $value

@return mixed


protected function get_value( Papi_Core_Conditional_Rule $rule ) {
		if ( papi_doing_ajax() ) {
			$source     = $rule->get_source();
			$meta_id    = papi_get_meta_id();
			$entry_type = papi_get_entry_type_by_meta_id( $meta_id );

			if ( ! papi_is_empty( $source ) && $entry_type instanceof Papi_Entry_Type !== false ) {
				if ( papi_is_property( $entry_type->get_property( $rule->slug ) ) ) {
					return $this->get_deep_value( $rule->slug, $source );
				}
			}
		}

		if ( ! papi_is_empty( $rule->get_source() ) ) {
			return $this->get_deep_value( $rule->slug, $rule->get_source() );
		}

		$slug  = $rule->get_field_slug();
		$type  = papi_get_meta_type();
		$value = papi_get_field( $slug, null, $type );

		return $this->get_deep_value( $slug, $value );
	}

protected function get_value ( Papi_Core_Conditional_Rule $ rule ) { if ( papi_doing_ajax ( ) ) { $ source = $ rule -> get_source ( ) ; $ meta_id = papi_get_meta_id ( ) ; $ entry_type = papi_get_entry_type_by_meta_id ( $ meta_id ) ; if ( ! papi_is_empty ( $ source ) && $ entry_type instanceof Papi_Entry_Type !== false ) { if ( papi_is_property ( $ entry_type -> get_property ( $ rule -> slug ) ) ) { return $ this -> get_deep_value ( $ rule -> slug , $ source ) ; } } } if ( ! papi_is_empty ( $ rule -> get_source ( ) ) ) { return $ this -> get_deep_value ( $ rule -> slug , $ rule -> get_source ( ) ) ; } $ slug = $ rule -> get_field_slug ( ) ; $ type = papi_get_meta_type ( ) ; $ value = papi_get_field ( $ slug , null , $ type ) ; return $ this -> get_deep_value ( $ slug , $ value ) ; }

Get property value.

@param  Papi_Core_Conditional_Rule $rule

@return mixed


public function rule_equal( Papi_Core_Conditional_Rule $rule ) {
		list( $value, $rule_value ) = $this->get_converted_value( $rule );
		return $value === $rule_value;
	}

public function rule_equal ( Papi_Core_Conditional_Rule $ rule ) { list ( $ value , $ rule_value ) = $ this -> get_converted_value ( $ rule ) ; return $ value === $ rule_value ; }

Equal conditional rule.

@param  Papi_Core_Conditional_Rule $rule

@return bool


public function rule_not_equal( Papi_Core_Conditional_Rule $rule ) {
		list( $value, $rule_value ) = $this->get_converted_value( $rule );
		return $value !== $rule_value;
	}

public function rule_not_equal ( Papi_Core_Conditional_Rule $ rule ) { list ( $ value , $ rule_value ) = $ this -> get_converted_value ( $ rule ) ; return $ value !== $ rule_value ; }

Not equal conditional rule.

@param  Papi_Core_Conditional_Rule $rule

@return bool


public function rule_greater_then( Papi_Core_Conditional_Rule $rule ) {
		$value = $this->get_value( $rule );

		if ( is_array( $value ) ) {
			$value = count( $value );
		}

		if ( ! is_numeric( $value ) || ! is_numeric( $rule->value ) ) {
			return false;
		}

		return $this->convert_number( $value ) >
			$this->convert_number( $rule->value );
	}

public function rule_greater_then ( Papi_Core_Conditional_Rule $ rule ) { $ value = $ this -> get_value ( $ rule ) ; if ( is_array ( $ value ) ) { $ value = count ( $ value ) ; } if ( ! is_numeric ( $ value ) || ! is_numeric ( $ rule -> value ) ) { return false ; } return $ this -> convert_number ( $ value ) > $ this -> convert_number ( $ rule -> value ) ; }

Greater then conditional rule.

@param  Papi_Core_Conditional_Rule $rule

@return bool


public function rule_not_in( Papi_Core_Conditional_Rule $rule ) {
		list( $value, $rule_value ) = $this->get_converted_value( $rule );

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

		return ! in_array( $value, $rule_value, true );
	}

public function rule_not_in ( Papi_Core_Conditional_Rule $ rule ) { list ( $ value , $ rule_value ) = $ this -> get_converted_value ( $ rule ) ; if ( ! is_array ( $ rule_value ) ) { return false ; } return ! in_array ( $ value , $ rule_value , true ) ; }

Not in array conditional rule.

@param  Papi_Core_Conditional_Rule $rule

@return bool


public function rule_like( Papi_Core_Conditional_Rule $rule ) {
		$value = $this->get_value( $rule );

		if ( ! is_string( $value ) ) {
			$value = papi_convert_to_string( $value );
		}

		if ( papi_is_empty( $value ) ) {
			return false;
		}

		return strpos(
			strtolower( $value ),
			strtolower( $rule->value )
		) !== false;
	}

public function rule_like ( Papi_Core_Conditional_Rule $ rule ) { $ value = $ this -> get_value ( $ rule ) ; if ( ! is_string ( $ value ) ) { $ value = papi_convert_to_string ( $ value ) ; } if ( papi_is_empty ( $ value ) ) { return false ; } return strpos ( strtolower ( $ value ) , strtolower ( $ rule -> value ) ) !== false ; }

Like conditional rule.

@param  Papi_Core_Conditional_Rule $rule

@return bool


protected function get_between_values( Papi_Core_Conditional_Rule $rule ) {
		$value = $this->get_value( $rule );

		if ( ! is_array( $rule->value ) ) {
			return [$rule, false];
		}

		foreach ( $rule->value as $index => $v ) {
			$v = $this->convert_number( $v );

			if ( is_numeric( $v ) ) {
				$rule->value[$index] = $v;
			} else {
				unset( $rule->value[$index] );
			}
		}

		if ( ! is_numeric( $value ) || count( $rule->value ) !== 2 ) {
			return [$rule, false];
		}

		return [$rule, $this->convert_number( $value )];
	}

protected function get_between_values ( Papi_Core_Conditional_Rule $ rule ) { $ value = $ this -> get_value ( $ rule ) ; if ( ! is_array ( $ rule -> value ) ) { return [ $ rule , false ] ; } foreach ( $ rule -> value as $ index => $ v ) { $ v = $ this -> convert_number ( $ v ) ; if ( is_numeric ( $ v ) ) { $ rule -> value [ $ index ] = $ v ; } else { unset ( $ rule -> value [ $ index ] ) ; } } if ( ! is_numeric ( $ value ) || count ( $ rule -> value ) !== 2 ) { return [ $ rule , false ] ; } return [ $ rule , $ this -> convert_number ( $ value ) ] ; }

Get between values.

@param  Papi_Core_Conditional_Rule $rule

@return array


public function rule_between( Papi_Core_Conditional_Rule $rule ) {
		list( $rule, $value ) = $this->get_between_values( $rule );

		if ( $value === false ) {
			return false;
		}

		return $rule->value[0] <= $value && $value <= $rule->value[1];
	}

public function rule_between ( Papi_Core_Conditional_Rule $ rule ) { list ( $ rule , $ value ) = $ this -> get_between_values ( $ rule ) ; if ( $ value === false ) { return false ; } return $ rule -> value [ 0 ] <= $ value && $ value <= $ rule -> value [ 1 ] ; }

Between conditional rule.

@param  Papi_Core_Conditional_Rule $rule

@return bool


public function rule_not_between( Papi_Core_Conditional_Rule $rule ) {
		list( $rule, $value ) = $this->get_between_values( $rule );

		if ( $value === false ) {
			return false;
		}

		return ! ( $rule->value[0] <= $value && $value <= $rule->value[1] );
	}

public function rule_not_between ( Papi_Core_Conditional_Rule $ rule ) { list ( $ rule , $ value ) = $ this -> get_between_values ( $ rule ) ; if ( $ value === false ) { return false ; } return ! ( $ rule -> value [ 0 ] <= $ value && $ value <= $ rule -> value [ 1 ] ) ; }

Not between conditional rule.

@param  Papi_Core_Conditional_Rule $rule

@return bool


public function get_sort_option( $post_id ) {
		$slug = $this->html_id( 'sort_option' );
		$slug = str_replace( '][', '_', $slug );
		$slug = str_replace( '[', '_', $slug );
		$slug = str_replace( ']', '', $slug );

		return papi_data_get( $post_id, $slug, $this->get_meta_type() );
	}

public function get_sort_option ( $ post_id ) { $ slug = $ this -> html_id ( 'sort_option' ) ; $ slug = str_replace ( '][' , '_' , $ slug ) ; $ slug = str_replace ( '[' , '_' , $ slug ) ; $ slug = str_replace ( ']' , '' , $ slug ) ; return papi_data_get ( $ post_id , $ slug , $ this -> get_meta_type ( ) ) ; }

Get sort option value.

@param  int $post_id

@return string


public static function get_sort_options() {
		$sort_options = [];

		$sort_options[__( 'Select', 'papi' )] = null;

		$sort_options[__( 'Name (alphabetically)', 'papi' )] = function ( $a, $b ) {
			// Backwards compatibility with both `post_title` and `title`.
			return strcmp(
				strtolower( isset( $a->post_title ) ? $a->post_title : $a->title ),
				strtolower( isset( $b->post_title ) ? $b->post_title : $b->title )
			);
		};

		$sort_options[__( 'Post created date (ascending)', 'papi' )] = function ( $a, $b ) {
			return strtotime( $a->post_date ) > strtotime( $b->post_date );
		};

		$sort_options[__( 'Post created date (descending)', 'papi' )] = function ( $a, $b ) {
			return strtotime( $a->post_date ) < strtotime( $b->post_date );
		};

		$sort_options[__( 'Post id (ascending)', 'papi' )] = function ( $a, $b ) {
			// Backwards compatibility with both `ID` and `id`.
			return isset( $a->ID ) ? $a->ID > $b->ID : $a->id > $b->id;
		};

		$sort_options[__( 'Post id (descending)', 'papi' )] = function ( $a, $b ) {
			// Backwards compatibility with both `ID` and `id`.
			return isset( $a->ID ) ? $a->ID < $b->ID : $a->id < $b->id;
		};

		$sort_options[__( 'Post order value (ascending)', 'papi' )] = function ( $a, $b ) {
			return $a->menu_order > $b->menu_order;
		};

		$sort_options[__( 'Post order value (descending)', 'papi' )] = function ( $a, $b ) {
			return $a->menu_order < $b->menu_order;
		};

		$sort_options[__( 'Post modified date (ascending)', 'papi' )] = function ( $a, $b ) {
			return strtotime( $a->post_modified ) > strtotime( $b->post_modified );
		};

		$sort_options[__( 'Post modified date (descending)', 'papi' )] = function ( $a, $b ) {
			return strtotime( $a->post_modified ) < strtotime( $b->post_modified );
		};

		return apply_filters( 'papi/property/relationship/sort_options', $sort_options );
	}

Get sort options for relationship property.

@return array

Get sort options for relationship property .


protected function get_items( $settings ) {
		if ( is_array( $settings->items ) && ! empty( $settings->items ) ) {
			$mapping = function ( $item ) {
				return is_array( $item ) ?
					isset( $item['id'], $item['title'] ) :
					isset( $item->id, $item->title );
			};

			return array_map(
				'papi_maybe_convert_to_object',
				array_filter( $settings->items, $mapping )
			);
		}

		// By default we add posts per page key with the value -1 (all).
		if ( ! isset( $settings->query['posts_per_page'] ) ) {
			$settings->query['posts_per_page'] = -1;
		}

		// Prepare arguments for WP_Query.
		$args = array_merge( [
			'post_status'            => 'any',
			'post_type'              => papi_to_array( $settings->post_type ),
			'no_found_rows'          => true,
			'update_post_meta_cache' => false,
			'update_post_term_cache' => false
		], $settings->query );

		$items = ( new WP_Query( $args ) )->posts;

		return array_map( [$this, 'convert_post_to_item'], papi_get_only_objects( $items ) );
	}

Get items to display from settings.

@param  stdClass $settings

@return array


public function sort_value( $values, $slug, $post_id ) {
		$sort_option  = $this->get_sort_option( $post_id );
		$sort_options = static::get_sort_options();

		if ( empty( $sort_option ) || ! isset( $sort_options[$sort_option] ) || is_null( $sort_options[$sort_option] ) ) {
			return $values;
		}

		usort( $values, $sort_options[$sort_option] );

		return $values;
	}

public function sort_value ( $ values , $ slug , $ post_id ) { $ sort_option = $ this -> get_sort_option ( $ post_id ) ; $ sort_options = static :: get_sort_options ( ) ; if ( empty ( $ sort_option ) || ! isset ( $ sort_options [ $ sort_option ] ) || is_null ( $ sort_options [ $ sort_option ] ) ) { return $ values ; } usort ( $ values , $ sort_options [ $ sort_option ] ) ; return $ values ; }

Sort the values.

@param  array  $values
@param  string $slug
@param  int    $post_id

@return array


public function update_value( $values, $slug, $post_id ) {
		$values = $this->format_value( $values, $slug, $post_id );
		$values = array_map( function ( $item ) {
			if ( $item instanceof WP_Post ) {
				$item = $this->convert_post_to_item( $item );
			}

			if ( isset( $item->title ) ) {
				unset( $item->title );
			}

			return $item;
		}, $values );

		return papi_maybe_json_decode( $values );
	}

public function update_value ( $ values , $ slug , $ post_id ) { $ values = $ this -> format_value ( $ values , $ slug , $ post_id ) ; $ values = array_map ( function ( $ item ) { if ( $ item instanceof WP_Post ) { $ item = $ this -> convert_post_to_item ( $ item ) ; } if ( isset ( $ item -> title ) ) { unset ( $ item -> title ) ; } return $ item ; } , $ values ) ; return papi_maybe_json_decode ( $ values ) ; }

Sort the values on update.

@param  mixed  $values
@param  string $slug
@param  int    $post_id

@return string


protected function get_meta_type_value( $entry_type ) {
		if ( in_array( $entry_type->get_type(), ['attachment'], true ) ) {
			return $entry_type->get_type();
		}

		switch ( papi_get_meta_type( $entry_type->get_type() ) ) {
			case 'post':
				return implode( ', ', $entry_type->post_type );
			case 'term':
				return implode( ', ', $entry_type->taxonomy );
			default:
				return 'n/a';
		}
	}

protected
function
get_meta_type_value
(
$
entry_type
)
{
if
(
in_array
(
$
entry_type
->
get_type
(
)
,
[
'attachment'
]
,
true
)
)
{
return
$
entry_type
->
get_type
(
)
;
}
switch
(
papi_get_meta_type
(
$
entry_type
->
get_type
(
)
)
)
{
case
'post'
:
return
implode
(
', '
,
$
entry_type
->
post_type
)
;
case
'term'
:
return
implode
(
', '
,
$
entry_type
->
taxonomy
)
;
default
:
return
'n/a'
;
}
}

Get meta type value.

@param  Papi_Entry_Type $entry_type

@return string


public function list_( $args, $assoc_args ) {
		// Get all entry types.
		$entry_types = papi_get_all_entry_types();

		if ( empty( $entry_types ) ) {
			WP_CLI::error( 'No Papi types exists.' );
		}

		// Create type item with the fields that
		// will be displayed.
		$entry_types = array_map( function( $entry_type ) {
			return [
				'id'              => $entry_type->get_id(),
				'name'            => $entry_type->name,
				'meta type value' => $this->get_meta_type_value( $entry_type ),
				'template'        => empty( $entry_type->template ) ? 'n/a' : $entry_type->template,
				'type'            => $entry_type->get_type(),
				'db count'        => $entry_type->get_type() === 'option' ? 'n/a' : papi_get_entry_type_count( $entry_type )
			];
		}, $entry_types );

		// Render types as a table.
		$formatter = $this->get_formatter( $assoc_args );
		$formatter->display_items( $entry_types );
	}

List Papi types.

## Options

[--<field>=<value>]
: Filter types based on type property.

[--field=<field>]
: Prints the value of a single field for each type.

[--fields=<fields>]
: Limit the output to specific type fields.

[--format=<format>]
: Acceptec values: table, csv, json, count, ids. Default: table.

## AVAILABLE FIELDS

These fields will be displayed by default for each type:

* name
* id
* post_type
* template
* number_of_pages
* type

Not all fields exists on a Papi type so some fields will have `n/a`
as value when no value can be displayed.

## EXAMPLES

wp papi type list

@subcommand list


protected function html() {
		?>

				<?php
				foreach ( $this->tabs as $tab ):
					$css_classes = $this->tabs[0] === $tab ? 'active ' : '';

					if ( empty( $tab->background ) ) {
						// Find out if the first property has a sidebar or not. If the first property
						// don't have a sidebar the tab background should be white since it looks better.
						$no_sidebar = empty( $tab->properties ) ? false : $tab->properties[0]->sidebar;
						$css_classes .= ! empty( $tab->properties ) && $no_sidebar ? '' : 'white-tab';
					} else {
						$css_classes .= $tab->background === 'white' ? 'white-tab' : '';
					}
					?>
					<li class="<?php echo esc_attr( $css_classes ); ?>">
						<a href="#" data-papi-tab="<?php echo esc_attr( $tab->id ); ?>">
							<?php if ( ! empty( $tab->icon ) ): ?>
								<img src="<?php echo esc_attr( $tab->icon ); ?>" alt="<?php echo esc_attr( $tab->title ); ?>" />
							<?php endif;
							echo esc_html( $tab->title ); ?>

				<?php endforeach; ?>

				<?php
				foreach ( $this->tabs as $tab ):
					?>
					<div class="<?php echo $this->tabs[0] === $tab ? 'active' : ''; ?>" data-papi-tab="<?php echo esc_attr( $tab->id ); ?>">
						<?php papi_render_properties( $tab->properties ); ?>

					<?php
				endforeach;
				?>

		<?php
	}

?>">
						<a href="#" data-papi-tab="<?php

?>
			</ul>
			<div class="papi-tabs-content">
				<?php


protected function get_json_id( $key, $extra = '' ) {
		return $this->get_slug() . '_' . papi_slugify( $key ) . ( empty( $extra ) ? '' : '_' . $extra );
	}

protected function get_json_id ( $ key , $ extra = '' ) { return $ this -> get_slug ( ) . '_' . papi_slugify ( $ key ) . ( empty ( $ extra ) ? '' : '_' . $ extra ) ; }

Generate layout slug.

@param  string $key
@param  string $extra

@return string


protected function get_layout( $slug ) {
		$layouts = $this->get_settings_layouts();

		foreach ( $layouts as $layout ) {
			if ( $layout['slug'] === $slug ) {
				return $layout;
			}
		}

		return [];
	}

protected function get_layout ( $ slug ) { $ layouts = $ this -> get_settings_layouts ( ) ; foreach ( $ layouts as $ layout ) { if ( $ layout [ 'slug' ] === $ slug ) { return $ layout ; } } return [ ] ; }

Get layout by slug.

@param  string $slug

@return array


public function load_value( $value, $repeater_slug, $post_id ) {
		if ( is_array( $value ) ) {
			return $value;
		}

		list( $results, $trash ) = $this->get_results( $value, $repeater_slug, $post_id );

		// Will not need this array.
		unset( $trash );

		$store   = $this->get_store();
		$results = papi_property_from_array_slugs( $results, unpapify( $repeater_slug ) );

		if ( is_null( $store ) ) {
			return $this->default_value;
		}

		return $this->load_child_properties( $results, $this );
	}

public
function
load_value
(
$
value
,
$
repeater_slug
,
$
post_id
)
{
if
(
is_array
(
$
value
)
)
{
return
$
value
;
}
list
(
$
results
,
$
trash
)
=
$
this
->
get_results
(
$
value
,
$
repeater_slug
,
$
post_id
)
;
// Will not need this array.
unset
(
$
trash
)
;
$
store
=
$
this
->
get_store
(
)
;
$
results
=
papi_property_from_array_slugs
(
$
results
,
unpapify
(
$
repeater_slug
)
)
;
if
(
is_null
(
$
store
)
)
{
return
$
this
->
default_value
;
}
return
$
this
->
load_child_properties
(
$
results
,
$
this
)
;
}

Change value after it's loaded from the database
and populate every property in the flexible with the right property type.

@param mixed  $value
@param string $repeater_slug
@param int    $post_id

@return array

Change value after it s loaded from the database and populate every property in the flexible with the right property type .


protected function prepare_properties( $layouts ) {
		$layouts = array_map( function ( $layout ) {
			return (array) $layout;
		}, $layouts );

		foreach ( $layouts as $index => $layout ) {
			if ( ! $this->valid_layout( $layout ) ) {
				if ( is_array( $layout ) ) {
					unset( $layout[$index] );
				} else {
					unset( $layouts[$index] );
				}

				continue;
			}

			if ( ! isset( $layout['slug'] ) ) {
				$layout['slug'] = $layout['title'];
			}

			if ( ! isset( $layout['row_label'] ) ) {
				$layout['row_label'] = $layout['title'];
			}

			if ( ! isset( $layout['show_label'] ) ) {
				$layout['show_label'] = true;
			}

			$layouts[$index] = array_merge( $layouts[$index], $layout );

			$layouts[$index]['slug']  = papi_slugify( $layout['slug'] );
			$layouts[$index]['slug']  = $this->get_layout_value( $layouts[$index]['slug'] );
			$layouts[$index]['items'] = parent::prepare_properties( $layout['items'] );
		}

		return array_filter( $layouts );
	}

protected function prepare_properties ( $ layouts ) { $ layouts = array_map ( function ( $ layout ) { return ( array ) $ layout ; } , $ layouts ) ; foreach ( $ layouts as $ index => $ layout ) { if ( ! $ this -> valid_layout ( $ layout ) ) { if ( is_array ( $ layout ) ) { unset ( $ layout [ $ index ] ) ; } else { unset ( $ layouts [ $ index ] ) ; } continue ; } if ( ! isset ( $ layout [ 'slug' ] ) ) { $ layout [ 'slug' ] = $ layout [ 'title' ] ; } if ( ! isset ( $ layout [ 'row_label' ] ) ) { $ layout [ 'row_label' ] = $ layout [ 'title' ] ; } if ( ! isset ( $ layout [ 'show_label' ] ) ) { $ layout [ 'show_label' ] = true ; } $ layouts [ $ index ] = array_merge ( $ layouts [ $ index ] , $ layout ) ; $ layouts [ $ index ] [ 'slug' ] = papi_slugify ( $ layout [ 'slug' ] ) ; $ layouts [ $ index ] [ 'slug' ] = $ this -> get_layout_value ( $ layouts [ $ index ] [ 'slug' ] ) ; $ layouts [ $ index ] [ 'items' ] = parent :: prepare_properties ( $ layout [ 'items' ] ) ; } return array_filter ( $ layouts ) ; }

Prepare properties.

Not the best name for this function, but since
property repeater using this we can't rename it.

@param  array $layouts

@return array


protected function render_layout_input( $value ) {
		$slug = sprintf( '%s[%d][%s]', $this->get_slug(), $this->counter, $this->layout_key );
		?>
		<input type="hidden" name="<?php echo esc_attr( $slug ); ?>" value="<?php echo esc_attr( $value ); ?>" />
		<?php
	}

Render layout input.

@param string $value


protected function render_repeater_row() {
		$layouts = $this->get_settings_layouts();
		$values  = $this->get_value();

		// Fetch all slugs in all layouts.
		$slugs = [];
		foreach ( $layouts as $index => $layout ) {
			foreach ( $layout['items'] as $item ) {
				$slugs[] = unpapify( $item->slug );
			}
		}

		// Remove values that don't exists in the slugs array.
		foreach ( $values as $index => $row ) {
			$keys = array_keys( $row );

			foreach ( array_keys( $row ) as $slug ) {
				if ( in_array( $slug, $keys, true ) || papi_is_property_type_key( $slug ) || $this->is_layout_key( $slug ) ) {
					continue;
				}

				unset( $values[$index][$slug] );
			}
		}

		$values      = array_filter( $values );
		$closed_rows = $this->get_setting( 'closed_rows', true );

		foreach ( $values as $index => $row ):
			?>

			<tr <?php echo $closed_rows ? 'class="closed"' : ''; ?>>

					<?php echo esc_html( $this->counter + 1 ); ?>

				<?php
				foreach ( $layouts as $layout ) {
					// Don't render layouts that don't have a valid value in the database.
					if ( ! isset( $row[$this->layout_key] ) || $layout['slug'] !== $this->get_layout_value( $row[$this->layout_key] ) ) {
						continue;
					}

					// Render all properties in the layout
					$this->render_properties( $layout['items'], $row );
				}

				$this->counter ++;
				?>

						<a title="<?php esc_html_e( 'Remove', 'papi' ); ?>" href="#" class="repeater-remove-item">x

			<?php
		endforeach;
	}

?>" href="#" class="repeater-remove-item">x</a>
					</span>
				</td>
			</tr>

			<?php


public function add_form_fields() {
		$html_name       = esc_attr( papi_get_page_type_key() );
		$taxonomy        = papi_get_qs( 'taxonomy' );
		$taxonomy_object = get_taxonomy( $taxonomy );

		// Get only the taxonomy types that has the taxonomy.
		$taxonomy_types = array_filter( $this->taxonomy_types, function ( $taxonomy_type ) use ( $taxonomy ) {
			return in_array( $taxonomy, $taxonomy_type->taxonomy, true ) && $taxonomy_type->display( $taxonomy );
		} );
		$taxonomy_types = array_values( $taxonomy_types );

		// Do not display empty select if no taxonomy types.
		if ( empty( $taxonomy_types ) ) {
			return;
		}

		// Prepare taxonomy types with standard taxonomy type.
		$taxonomy_types = $this->prepare_taxonomy_types( $taxonomy_types );

		// Render a dropdown if more than one taxonomy types
		// exists on the taxonomy.
		if ( count( $taxonomy_types ) > 1 ):
			?>
			<div class="form-field">
				<label for="<?php echo esc_attr( $html_name ); ?>">
					<?php echo esc_html( sprintf( __( '%s type', 'papi' ), $taxonomy_object->labels->singular_name ) ); ?>
				</label>
				<select name="<?php echo esc_attr( $html_name ); ?>" id="<?php echo esc_attr( $html_name ); ?>" data-papi-page-type-key="true">
					<?php
					foreach ( $taxonomy_types as $taxonomy_type ) {
						papi_render_html_tag( 'option', [
							'data-redirect' => $taxonomy_type->redirect_after_create,
							'value'         => esc_attr( $taxonomy_type->get_id() ),
							esc_html( $taxonomy_type->name )
						] );
					}
					?>
				</select>
			</div>
			<?php
		else:
			papi_render_html_tag( 'input', [
				'data-redirect'           => $taxonomy_types[0]->redirect_after_create,
				'data-papi-page-type-key' => true,
				'name'                    => esc_attr( $html_name ),
				'type'                    => 'hidden',
				'value'                   => esc_attr( $taxonomy_types[0]->get_id() )
			] );
		endif;
	}


protected function prepare_taxonomy_types( array $taxonomy_types ) {
		$taxonomy = papi_get_qs( 'taxonomy' );

		if ( papi_filter_settings_show_standard_taxonomy_type( $taxonomy ) ) {
			$id                      = sprintf( 'papi-standard-%s-type', $taxonomy );
			$taxonomy_type           = new Papi_Taxonomy_Type( $id );
			$taxonomy_type->id       = $id;
			$taxonomy_type->name     = papi_filter_settings_standard_taxonomy_type_name( $taxonomy );
			$taxonomy_type->taxonomy = [$taxonomy];
			$taxonomy_types[]        = $taxonomy_type;
		}

		usort( $taxonomy_types, function ( $a, $b ) {
			return strcmp( $a->name, $b->name );
		} );

		return papi_sort_order( array_reverse( $taxonomy_types ) );
	}

Prepare taxonomy types, add standard taxonomy if it should be added.

@param  array $taxonomy_types

@return array

Prepare taxonomy types add standard taxonomy if it should be added .


public function setup_taxonomies_hooks() {
		$this->taxonomy_types = papi_get_all_entry_types( [
			'types' => 'taxonomy'
		] );

		$taxonomies = array_reduce( $this->taxonomy_types, function ( $taxonomies, $taxonomy_type ) {
			return array_merge( $taxonomies, $taxonomy_type->taxonomy );
		}, [] );
		$taxonomies = array_unique( $taxonomies );

		foreach ( $taxonomies as $taxonomy ) {
			if ( is_string( $taxonomy ) && taxonomy_exists( $taxonomy ) ) {
				add_action( $taxonomy . '_add_form_fields', [$this, 'add_form_fields'] );
			}
		}
	}

public function setup_taxonomies_hooks ( ) { $ this -> taxonomy_types = papi_get_all_entry_types ( [ 'types' => 'taxonomy' ] ) ; $ taxonomies = array_reduce ( $ this -> taxonomy_types , function ( $ taxonomies , $ taxonomy_type ) { return array_merge ( $ taxonomies , $ taxonomy_type -> taxonomy ) ; } , [ ] ) ; $ taxonomies = array_unique ( $ taxonomies ) ; foreach ( $ taxonomies as $ taxonomy ) { if ( is_string ( $ taxonomy ) && taxonomy_exists ( $ taxonomy ) ) { add_action ( $ taxonomy . '_add_form_fields' , [ $ this , 'add_form_fields' ] ) ; } } }


public function ajax_url() {
		if ( empty( $this->structure ) ) {
			$url = esc_url( home_url( 'index.php', is_ssl() ? 'https' : 'http' ) );
		} else {
			$url = esc_url( home_url( '/papi-ajax/', is_ssl() ? 'https' : 'http' ) );
		}
		?>
		<script type="text/javascript">
			var papi = papi || {};
			papi.ajaxUrl = '<?php echo esc_html( $url ); ?>';
		</script>
		<?php
	}

Add ajax url to Papi JavaScript object .


public function handle_papi_ajax() {
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
			return;
		}

		$ajax_action = '';

		if ( ! empty( $_GET['action'] ) ) {
			$ajax_action = sanitize_text_field( $_GET['action'] );
		}

		if ( is_user_logged_in() && has_action( $this->action_prefix . $ajax_action ) !== false ) {
			if ( ! defined( 'DOING_AJAX' ) ) {
				define( 'DOING_AJAX', true );
			}

			if ( ! defined( 'DOING_PAPI_AJAX' ) ) {
				define( 'DOING_PAPI_AJAX', true );
			}

			status_header( 200 );
			do_action( $this->action_prefix . $ajax_action );
			wp_die();
		}
	}

public function handle_papi_ajax ( ) { if ( defined ( 'DOING_AJAX' ) && DOING_AJAX ) { return ; } $ ajax_action = '' ; if ( ! empty ( $ _GET [ 'action' ] ) ) { $ ajax_action = sanitize_text_field ( $ _GET [ 'action' ] ) ; } if ( is_user_logged_in ( ) && has_action ( $ this -> action_prefix . $ ajax_action ) !== false ) { if ( ! defined ( 'DOING_AJAX' ) ) { define ( 'DOING_AJAX' , true ) ; } if ( ! defined ( 'DOING_PAPI_AJAX' ) ) { define ( 'DOING_PAPI_AJAX' , true ) ; } status_header ( 200 ) ; do_action ( $ this -> action_prefix . $ ajax_action ) ; wp_die ( ) ; } }


public function get_entry_type() {
		$entry_type_id = papi_get_qs( 'entry_type' );
		$entry_type    = papi_get_entry_type_by_id( $entry_type_id );

		if ( empty( $entry_type ) ) {
			$this->render_error( 'No entry type found' );
			return;
		}

		wp_send_json( $entry_type );
	}

public
function
get_entry_type
(
)
{
$
entry_type_id
=
papi_get_qs
(
'entry_type'
)
;
$
entry_type
=
papi_get_entry_type_by_id
(
$
entry_type_id
)
;
if
(
empty
(
$
entry_type
)
)
{
$
this
->
render_error
(
'No entry type found'
)
;
return
;
}
wp_send_json
(
$
entry_type
)
;
}

Get entry type via GET.

GET /papi-ajax/?action=get_entry_type


public function get_posts() {
		$args   = papi_get_qs( 'query' ) ?: [];
		$args   = is_array( $args ) ? $args : [];
		$fields = papi_get_qs( 'fields' ) ?: [];
		$fields = is_array( $fields ) ? $fields : [];
		$posts  = ( new WP_Query( array_merge( [
			'posts_per_page'         => -1,
			'post_status'            => 'any',
			'post_type'              => ['post'],
			'no_found_rows'          => true,
			'update_post_meta_cache' => false,
			'update_post_term_cache' => false
		], $args ) ) )->posts;

		$posts = array_filter( $posts, function ( $post ) {
			return ! empty( $post->post_title );
		} );

		usort( $posts, function ( $a, $b ) {
			return strcmp( strtolower( $a->post_title ), strtolower( $b->post_title ) );
		} );

		if ( ! empty( $fields ) ) {
			foreach ( $posts as $index => $post ) {
				$item = [];

				foreach ( $fields as $field ) {
					$item[$field] = $post->$field;
				}

				$posts[$index] = $item;
			}
		}

		wp_send_json( $posts );
	}

public function get_posts ( ) { $ args = papi_get_qs ( 'query' ) ? : [ ] ; $ args = is_array ( $ args ) ? $ args : [ ] ; $ fields = papi_get_qs ( 'fields' ) ? : [ ] ; $ fields = is_array ( $ fields ) ? $ fields : [ ] ; $ posts = ( new WP_Query ( array_merge ( [ 'posts_per_page' => - 1 , 'post_status' => 'any' , 'post_type' => [ 'post' ] , 'no_found_rows' => true , 'update_post_meta_cache' => false , 'update_post_term_cache' => false ] , $ args ) ) ) -> posts ; $ posts = array_filter ( $ posts , function ( $ post ) { return ! empty ( $ post -> post_title ) ; } ) ; usort ( $ posts , function ( $ a , $ b ) { return strcmp ( strtolower ( $ a -> post_title ) , strtolower ( $ b -> post_title ) ) ; } ) ; if ( ! empty ( $ fields ) ) { foreach ( $ posts as $ index => $ post ) { $ item = [ ] ; foreach ( $ fields as $ field ) { $ item [ $ field ] = $ post -> $ field ; } $ posts [ $ index ] = $ item ; } } wp_send_json ( $ posts ) ; }

Get posts via GET.

Posts with empty title will be ignored.

GET /papi-ajax/?action=get_posts


public function get_property() {
		$default_options = Papi_Core_Property::factory()->get_options();
		$keys            = array_keys( get_object_vars( $default_options ) );
		$options         = papi_get_qs( $keys, true );

		if ( $property = papi_property( $options ) ) {
			ob_start();

			$property->render_ajax_request();

			$html = ob_get_clean();

			wp_send_json( [
				'html' => utf8_encode( $html )
			] );

			return;
		}

		$this->render_error( 'No property found' );
	}

public
function
get_property
(
)
{
$
default_options
=
Papi_Core_Property
::
factory
(
)
->
get_options
(
)
;
$
keys
=
array_keys
(
get_object_vars
(
$
default_options
)
)
;
$
options
=
papi_get_qs
(
$
keys
,
true
)
;
if
(
$
property
=
papi_property
(
$
options
)
)
{
ob_start
(
)
;
$
property
->
render_ajax_request
(
)
;
$
html
=
ob_get_clean
(
)
;
wp_send_json
(
[
'html'
=>
utf8_encode
(
$
html
)
]
)
;
return
;
}
$
this
->
render_error
(
'No property found'
)
;
}

Get property html via GET.

GET /papi-ajax/?action=get_property


public function get_properties() {
		if ( ! papi_get_sanitized_post( 'properties' ) ) {
			$this->render_error( 'No properties found' );

			return;
		}

		$items = json_decode( stripslashes( $_POST['properties'] ), true );

		if ( empty( $items ) || ! is_array( $items ) ) {
			$this->render_error( 'No properties found' );

			return;
		}

		foreach ( $items as $key => $item ) {
			$property = papi_property( (array) $item );

			if ( ! papi_is_property( $property ) ) {
				unset( $items[$key] );
				continue;
			}

			ob_start();

			$property->render_ajax_request();

			$items[$key] = trim( ob_get_clean() );
		}

		$items = array_filter( $items );

		if ( empty( $items ) ) {
			$this->render_error( 'No properties found' );

			return;
		}

		wp_send_json( [
			'html' => $items
		] );
	}

public
function
get_properties
(
)
{
if
(
!
papi_get_sanitized_post
(
'properties'
)
)
{
$
this
->
render_error
(
'No properties found'
)
;
return
;
}
$
items
=
json_decode
(
stripslashes
(
$
_POST
[
'properties'
]
)
,
true
)
;
if
(
empty
(
$
items
)
||
!
is_array
(
$
items
)
)
{
$
this
->
render_error
(
'No properties found'
)
;
return
;
}
foreach
(
$
items
as
$
key
=>
$
item
)
{
$
property
=
papi_property
(
(
array
)
$
item
)
;
if
(
!
papi_is_property
(
$
property
)
)
{
unset
(
$
items
[
$
key
]
)
;
continue
;
}
ob_start
(
)
;
$
property
->
render_ajax_request
(
)
;
$
items
[
$
key
]
=
trim
(
ob_get_clean
(
)
)
;
}
$
items
=
array_filter
(
$
items
)
;
if
(
empty
(
$
items
)
)
{
$
this
->
render_error
(
'No properties found'
)
;
return
;
}
wp_send_json
(
[
'html'
=>
$
items
]
)
;
}

Get properties via POST.

POST /papi-ajax/?action=get_properties


public function get_rules_result() {
		if ( ! papi_get_sanitized_post( 'data' ) ) {
			$this->render_error( 'No rule found' );

			return;
		}

		$data = json_decode( stripslashes( papi_get_sanitized_post( 'data' ) ), true );

		if ( empty( $data ) || ! is_array( $data ) || ! isset( $data['slug'] ) ) {
			$this->render_error( 'No rule found' );

			return;
		}

		$entry_type = papi_get_entry_type_by_meta_id();

		if ( empty( $entry_type ) ) {
			$entry_type_id = papi_get_qs( 'entry_type' );
			$entry_type    = papi_get_entry_type_by_id( $entry_type_id );
		}

		if ( $entry_type instanceof Papi_Entry_Type === false ) {
			$this->render_error( 'No rule found' );

			return;
		}

		if ( preg_match( '/\[\]$/', $data['slug'] ) ) {
			$data['slug'] = preg_replace( '/\[\]$/', '', $data['slug'] );
		}

		if ( $property = $entry_type->get_property( $data['slug'] ) ) {
			wp_send_json( [
				'render' => $property->render_is_allowed_by_rules( $data['rules'] )
			] );

			return;
		}

		$this->render_error( 'No rule found' );
	}

public
function
get_rules_result
(
)
{
if
(
!
papi_get_sanitized_post
(
'data'
)
)
{
$
this
->
render_error
(
'No rule found'
)
;
return
;
}
$
data
=
json_decode
(
stripslashes
(
papi_get_sanitized_post
(
'data'
)
)
,
true
)
;
if
(
empty
(
$
data
)
||
!
is_array
(
$
data
)
||
!
isset
(
$
data
[
'slug'
]
)
)
{
$
this
->
render_error
(
'No rule found'
)
;
return
;
}
$
entry_type
=
papi_get_entry_type_by_meta_id
(
)
;
if
(
empty
(
$
entry_type
)
)
{
$
entry_type_id
=
papi_get_qs
(
'entry_type'
)
;
$
entry_type
=
papi_get_entry_type_by_id
(
$
entry_type_id
)
;
}
if
(
$
entry_type
instanceof
Papi_Entry_Type
===
false
)
{
$
this
->
render_error
(
'No rule found'
)
;
return
;
}
if
(
preg_match
(
'/\[\]$/'
,
$
data
[
'slug'
]
)
)
{
$
data
[
'slug'
]
=
preg_replace
(
'/\[\]$/'
,
''
,
$
data
[
'slug'
]
)
;
}
if
(
$
property
=
$
entry_type
->
get_property
(
$
data
[
'slug'
]
)
)
{
wp_send_json
(
[
'render'
=>
$
property
->
render_is_allowed_by_rules
(
$
data
[
'rules'
]
)
]
)
;
return
;
}
$
this
->
render_error
(
'No rule found'
)
;
}

Get rules result via GET.

GET /papi-ajax/?action=get_rules_result


public function get_shortcode() {
		$shortcode = papi_get_qs( 'shortcode' ) ?: '';
		$shortcode = html_entity_decode( $shortcode );
		$shortcode = wp_unslash( $shortcode );

		wp_send_json( [
			'html' => do_shortcode( $shortcode )
		] );
	}

public function get_shortcode ( ) { $ shortcode = papi_get_qs ( 'shortcode' ) ? : '' ; $ shortcode = html_entity_decode ( $ shortcode ) ; $ shortcode = wp_unslash ( $ shortcode ) ; wp_send_json ( [ 'html' => do_shortcode ( $ shortcode ) ] ) ; }

Get shortcode via GET.

GET /papi-ajax/?action=get_shortcode


public function get_terms() {
		$query    = papi_get_qs( 'query' ) ?: [];
		$query    = is_array( $query ) ? $query : [];
		$taxonomy = papi_get_qs( 'taxonomy' ) ?: '';

		$args = array_merge( $query, [
			'fields' => 'id=>name'
		] );

		$terms = [];
		if ( taxonomy_exists( $taxonomy ) ) {
			$terms = get_terms( $taxonomy, $args );
		}

		wp_send_json( $terms );
	}

public function get_terms ( ) { $ query = papi_get_qs ( 'query' ) ? : [ ] ; $ query = is_array ( $ query ) ? $ query : [ ] ; $ taxonomy = papi_get_qs ( 'taxonomy' ) ? : '' ; $ args = array_merge ( $ query , [ 'fields' => 'id=>name' ] ) ; $ terms = [ ] ; if ( taxonomy_exists ( $ taxonomy ) ) { $ terms = get_terms ( $ taxonomy , $ args ) ; } wp_send_json ( $ terms ) ; }

Get terms via GET.

GET /papi-ajax/?action=get_terms