1203 lines
32 KiB
PHP
1203 lines
32 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Fields - Base class
|
|
* Core properties/methods for fields
|
|
* @package Simple Lightbox
|
|
* @subpackage Fields
|
|
* @author Archetyped
|
|
*/
|
|
class SLB_Field_Base extends SLB_Base {
|
|
/*-** Config **-*/
|
|
protected $mode = 'object';
|
|
protected $shared = false;
|
|
|
|
/*-** Properties **-*/
|
|
|
|
/**
|
|
* @var string Unique name
|
|
*/
|
|
public $id = '';
|
|
|
|
/**
|
|
* ID formatting options.
|
|
*
|
|
* @var array $id_formats
|
|
*/
|
|
private $id_formats = [];
|
|
|
|
/**
|
|
* Flag for ID format initialization status.
|
|
*
|
|
* @var bool $id_formats_init
|
|
*/
|
|
private $id_formats_init = false;
|
|
|
|
/**
|
|
* Special characters/phrases
|
|
* Used for preserving special characters during formatting
|
|
* Merged with $special_chars_default
|
|
* Array Structure
|
|
* > Key: Special character/phrase
|
|
* > Value: Placeholder for special character
|
|
* @var array
|
|
*/
|
|
public $special_chars = null;
|
|
|
|
public $special_chars_default = array(
|
|
'{' => '%SQB_L%',
|
|
'}' => '%SQB_R%',
|
|
);
|
|
|
|
/**
|
|
* Reference to parent object that current instance inherits from
|
|
* @var object
|
|
*/
|
|
public $parent = null;
|
|
|
|
/**
|
|
* Title
|
|
* @var string
|
|
*/
|
|
public $title = '';
|
|
|
|
/**
|
|
* @var string Short description
|
|
*/
|
|
public $description = '';
|
|
|
|
/**
|
|
* @var array Object Properties
|
|
*/
|
|
public $properties = array();
|
|
|
|
/**
|
|
* Initialization properties
|
|
* @var array
|
|
*/
|
|
protected $properties_init = null;
|
|
|
|
/**
|
|
* Structure: Property names stored as keys in group
|
|
* Root
|
|
* -> Group Name
|
|
* -> Property Name => Null
|
|
* Reason: Faster searching over large arrays
|
|
* @var array Groupings of Properties
|
|
*/
|
|
public $property_groups = array();
|
|
|
|
/**
|
|
* Keys to filter out of properties array before setting properties
|
|
* @var array
|
|
*/
|
|
public $property_filter = array( 'group' );
|
|
|
|
/**
|
|
* Define order of properties
|
|
* Useful when processing order is important (e.g. one property depends on another)
|
|
* @var array
|
|
*/
|
|
public $property_priority = array();
|
|
|
|
/**
|
|
* Data for object
|
|
* May also contain data for nested objects
|
|
* @var mixed
|
|
*/
|
|
public $data = null;
|
|
|
|
/**
|
|
* Whether data has been fetched or not
|
|
* @var bool
|
|
*/
|
|
protected $data_loaded = false;
|
|
|
|
/**
|
|
* @var array Script resources to include for object
|
|
*/
|
|
public $scripts = array();
|
|
|
|
/**
|
|
* @var array CSS style resources to include for object
|
|
*/
|
|
public $styles = array();
|
|
|
|
/**
|
|
* Hooks (Filters/Actions) for object
|
|
* @var array
|
|
*/
|
|
public $hooks = array();
|
|
|
|
/**
|
|
* Mapping of child properties to parent members
|
|
* Allows more flexibility when creating new instances of child objects using property arrays
|
|
* Associative array structure:
|
|
* > Key: Child property to map FROM
|
|
* > Val: Parent property to map TO
|
|
* @var array
|
|
*/
|
|
public $map = null;
|
|
|
|
/**
|
|
* Options used when building collection (callbacks, etc.)
|
|
* Associative array
|
|
* > Key: Option name
|
|
* > Value: Option value
|
|
* @var array
|
|
*/
|
|
public $build_vars = array();
|
|
|
|
public $build_vars_default = array();
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
function __construct( $id = '', $properties = null ) {
|
|
parent::__construct();
|
|
// Normalize Properties
|
|
$args = func_get_args();
|
|
$defaults = $this->integrate_id( $id );
|
|
$properties = $this->make_properties( $args, $defaults );
|
|
// Save init properties
|
|
$this->properties_init = $properties;
|
|
// Set Properties
|
|
$this->set_properties( $properties );
|
|
}
|
|
|
|
/* Getters/Setters */
|
|
|
|
/**
|
|
* Checks if the specified path exists in the object
|
|
* @param array $path Path to check for
|
|
* @return bool TRUE if path exists in object, FALSE otherwise
|
|
*/
|
|
function path_isset( $path = '' ) {
|
|
// Stop execution if no path is supplied
|
|
if ( empty( $path ) ) {
|
|
return false;
|
|
}
|
|
$args = func_get_args();
|
|
$path = $this->util->build_path( $args );
|
|
$item =& $this;
|
|
// Iterate over path and check if each level exists before moving on to the next
|
|
$path_size = count( $path );
|
|
for ( $x = 0; $x < $path_size; $x++ ) {
|
|
if ( $this->util->property_exists( $item, $path[ $x ] ) ) {
|
|
// Set $item as reference to next level in path for next iteration
|
|
$item =& $this->util->get_property( $item, $path[ $x ] );
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Retrieves a value from object using a specified path
|
|
* Checks to make sure path exists in object before retrieving value
|
|
* @param array $path Path to retrieve value from. Each item in array is a deeper dimension
|
|
* @return mixed Value at specified path
|
|
*/
|
|
function &get_path_value( $path = '' ) {
|
|
$ret = '';
|
|
$path = $this->util->build_path( func_get_args() );
|
|
if ( $this->path_isset( $path ) ) {
|
|
$ret =& $this;
|
|
|
|
$path_size = count( $path );
|
|
for ( $x = 0; $x < $path_size; $x++ ) {
|
|
if ( 0 === $x ) {
|
|
$ret =& $ret->{ $path[ $x ] };
|
|
} else {
|
|
$ret =& $ret[ $path[ $x ] ];
|
|
}
|
|
}
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Search for specified member value in field type ancestors
|
|
* @param string $member Name of object member to search (e.g. properties, layout, etc.)
|
|
* @param string $name Value to retrieve from member
|
|
* @return mixed Member value if found (Default: empty string)
|
|
*/
|
|
function get_parent_value( $member, $name = '', $default = '' ) {
|
|
$parent = $this->get_parent();
|
|
return $this->get_object_value( $parent, $member, $name, $default, 'parent' );
|
|
}
|
|
|
|
/**
|
|
* Retrieves specified member value.
|
|
*
|
|
* Handles inherited values and merges corresponding parents
|
|
* if value is an array (e.g. for property groups).
|
|
*
|
|
* @param string|array $member Member to get value from.
|
|
* @param string|array $name Optional. Element/Path to Element to retrieve from member. Default none.
|
|
* @param mixed $default Optional. Default value to return if no data retrieved. Default empty string.
|
|
* @param string $dir Optional. Direction to move through hierarchy to find value.
|
|
* Possible Values:
|
|
* * parent (default) - Search through field parents.
|
|
* * current - Do not search through connected objects.
|
|
* * container - Search through field containers.
|
|
* * caller - Search through field callers.
|
|
* @return mixed Specified member value.
|
|
* @todo Return reference.
|
|
*/
|
|
function &get_member_value( $member, $name = '', $default = '', $dir = 'parent' ) {
|
|
// Check if path to member is supplied
|
|
$path = array();
|
|
if ( is_array( $member ) && isset( $member['tag'] ) ) {
|
|
if ( isset( $member['attributes']['ref_base'] ) ) {
|
|
if ( 'root' !== $member['attributes']['ref_base'] ) {
|
|
$path[] = $member['attributes']['ref_base'];
|
|
}
|
|
} else {
|
|
$path[] = 'properties';
|
|
}
|
|
|
|
$path[] = $member['tag'];
|
|
} else {
|
|
$path = $member;
|
|
}
|
|
// Prep name.
|
|
if ( is_string( $name ) ) {
|
|
$name = trim( $name );
|
|
}
|
|
$path = $this->util->build_path( $path, $name );
|
|
// Set defaults and prepare data
|
|
$val = $default;
|
|
$inherit = false;
|
|
$inherit_tag = '{inherit}';
|
|
|
|
/**
|
|
* Determines whether the value must be retrieved from a parent/container object.
|
|
*
|
|
* Conditions:
|
|
*
|
|
* 1. Path does not exist in current field.
|
|
* 2. Path exists and is not an object, but at least one of the following is true:
|
|
* * Value at path is an array (e.g. properties, elements, etc. array):
|
|
* * - Parent/container values should be merged with retrieved array.
|
|
* * Value at path is a string that inherits from another field:
|
|
* * - Value from other field will be retrieved and will replace
|
|
* inheritance placeholder in retrieved value
|
|
* @var bool
|
|
*/
|
|
$deeper = false;
|
|
|
|
if ( ! $this->path_isset( $path ) ) {
|
|
$deeper = true;
|
|
} else {
|
|
$val = $this->get_path_value( $path );
|
|
if ( is_array( $val ) ) {
|
|
$deeper = true;
|
|
} elseif ( is_string( $val ) && false !== strpos( $val, $inherit_tag ) ) {
|
|
$deeper = true;
|
|
// Value inherits from another field.
|
|
$inherit = true;
|
|
}
|
|
}
|
|
|
|
if ( $deeper && 'current' !== $dir ) {
|
|
$ex_val = '';
|
|
// Get Parent value (recursive)
|
|
if ( 'parent' === $dir ) {
|
|
$ex_val = $this->get_parent_value( $member, $name, $default );
|
|
} elseif ( method_exists( $this, 'get_container_value' ) ) {
|
|
$ex_val = $this->get_container_value( $member, $name, $default );
|
|
}
|
|
// Handle inheritance
|
|
if ( is_array( $val ) ) {
|
|
// Combine Arrays
|
|
if ( is_array( $ex_val ) ) {
|
|
$val = array_merge( $ex_val, $val );
|
|
}
|
|
} elseif ( false !== $inherit ) {
|
|
// Replace placeholder with inherited string
|
|
$val = str_replace( $inherit_tag, $ex_val, $val );
|
|
} else {
|
|
// Default: Set parent value as value
|
|
$val = $ex_val;
|
|
}
|
|
}
|
|
|
|
return $val;
|
|
}
|
|
|
|
/**
|
|
* Search for specified member value in an object
|
|
* @param object $object Reference to object to retrieve value from
|
|
* @param string $member Name of object member to search (e.g. properties, layout, etc.)
|
|
* @param string $name (optional) Value to retrieve from member
|
|
* @param mixed $default (optional) Default value to use if no value found (Default: empty string)
|
|
* @param string $dir Direction to move through hierarchy to find value @see SLB_Field_Type::get_member_value() for possible values
|
|
* @return mixed Member value if found (Default: $default)
|
|
*/
|
|
function get_object_value( &$object, $member, $name = '', $default = '', $dir = 'parent' ) {
|
|
$ret = $default;
|
|
if ( is_object( $object ) && method_exists( $object, 'get_member_value' ) ) {
|
|
$ret = $object->get_member_value( $member, $name, $default, $dir );
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Set item ID
|
|
* @param string $id Unique item ID
|
|
*/
|
|
function set_id( $id ) {
|
|
if ( empty( $id ) || ! is_string( $id ) ) {
|
|
return false;
|
|
}
|
|
$this->id = trim( $id );
|
|
}
|
|
|
|
/**
|
|
* Retrieves field ID
|
|
* @param array|string $options (optional) Options or ID of format to use
|
|
* @return string item ID
|
|
*/
|
|
function get_id( $options = array() ) {
|
|
$item_id = trim( $this->id );
|
|
$formats = $this->get_id_formats();
|
|
// Setup options
|
|
$wrap_default = array(
|
|
'open' => '',
|
|
'close' => '',
|
|
'segment_open' => '',
|
|
'segment_close' => '',
|
|
);
|
|
|
|
$options_default = array(
|
|
'format' => null,
|
|
'wrap' => array(),
|
|
'segments_pre' => null,
|
|
'prefix' => '',
|
|
'recursive' => false,
|
|
);
|
|
|
|
// Load options based on format
|
|
if ( ! is_array( $options ) ) {
|
|
$options = array( 'format' => $options );
|
|
}
|
|
if ( isset( $options['format'] ) && is_string( $options['format'] ) && isset( $formats[ $options['format'] ] ) ) {
|
|
$options_default = wp_parse_args( $formats[ $options['format'] ], $options_default );
|
|
} else {
|
|
unset( $options['format'] );
|
|
}
|
|
$options = wp_parse_args( $options, $options_default );
|
|
// Import options into function
|
|
extract( $options );
|
|
|
|
// Validate options
|
|
$wrap = wp_parse_args( $wrap, $wrap_default );
|
|
|
|
if ( ! is_array( $segments_pre ) ) {
|
|
$segments_pre = array( $segments_pre );
|
|
}
|
|
$segments_pre = array_reverse( $segments_pre );
|
|
|
|
// Format ID based on options
|
|
$item_id = array( $item_id );
|
|
|
|
// Add parent objects to ID
|
|
if ( ! ! $recursive ) {
|
|
// Create array of ID components
|
|
$m = 'get_caller';
|
|
$c = ( method_exists( $this, $m ) ) ? $this->{$m}() : null;
|
|
while ( ! ! $c ) {
|
|
// Add ID of current caller to array
|
|
if ( method_exists( $c, 'get_id' ) && ! strlen( $c->get_id() ) > 0 ) {
|
|
$item_id = $c->get_id();
|
|
}
|
|
// Get parent object
|
|
$c = ( method_exists( $c, $m ) ) ? $c->{$m}() : null;
|
|
}
|
|
unset( $c );
|
|
}
|
|
|
|
// Additional segments (Pre)
|
|
foreach ( $segments_pre as $seg ) {
|
|
if ( is_null( $seg ) ) {
|
|
continue;
|
|
}
|
|
if ( is_object( $seg ) ) {
|
|
$seg = (array) $seg;
|
|
}
|
|
if ( is_array( $seg ) ) {
|
|
$item_id = array_merge( $item_id, array_reverse( $seg ) );
|
|
} elseif ( '' !== strval( $seg ) ) {
|
|
$item_id[] = strval( $seg );
|
|
}
|
|
}
|
|
|
|
// Prefix
|
|
if ( is_array( $prefix ) ) {
|
|
// Array is sequence of instance methods to call on object
|
|
// Last array member can be an array of parameters to pass to methods
|
|
$count = count( $prefix );
|
|
$args = ( $count > 1 && is_array( $prefix[ $count - 1 ] ) ) ? array_pop( $prefix ) : array();
|
|
$p = $this;
|
|
$val = '';
|
|
// Iterate through methods
|
|
foreach ( $prefix as $m ) {
|
|
if ( ! method_exists( $p, $m ) ) {
|
|
continue;
|
|
}
|
|
// Build callback
|
|
$m = $this->util->m( $p, $m );
|
|
// Call callback
|
|
$val = call_user_func_array( $m, $args );
|
|
// Returned value may be an instance object
|
|
if ( is_object( $val ) ) {
|
|
$p = $val; // Use returned object in next round
|
|
} else {
|
|
array_unshift( $args, $val ); // Pass returned value as parameter to next method on using current object
|
|
}
|
|
}
|
|
$prefix = $val;
|
|
unset( $p, $val );
|
|
}
|
|
if ( is_numeric( $prefix ) ) {
|
|
$prefix = strval( $prefix );
|
|
}
|
|
if ( empty( $prefix ) || ! is_string( $prefix ) ) {
|
|
$prefix = '';
|
|
}
|
|
|
|
// Convert array to string
|
|
$item_id = $prefix . $wrap['open'] . implode( $wrap['segment_close'] . $wrap['segment_open'], array_reverse( $item_id ) ) . $wrap['close'];
|
|
return $item_id;
|
|
}
|
|
|
|
/**
|
|
* Retrieves ID formats.
|
|
*
|
|
* @return array ID formats.
|
|
*/
|
|
private function &get_id_formats() {
|
|
$this->init_id_formats();
|
|
return $this->id_formats;
|
|
}
|
|
|
|
/**
|
|
* Initializes default ID formats.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @return void
|
|
*/
|
|
private function init_id_formats() {
|
|
if ( ! $this->id_formats_init ) {
|
|
$this->id_formats_init = true;
|
|
// Initilize default formats.
|
|
$this->add_id_format(
|
|
'attr_id',
|
|
[
|
|
'wrap' => [
|
|
'open' => '_',
|
|
'segment_open' => '_',
|
|
],
|
|
'prefix' => [ 'get_container', 'get_id', 'add_prefix' ],
|
|
'recursive' => true,
|
|
],
|
|
true
|
|
);
|
|
$this->add_id_format(
|
|
'attr_name',
|
|
[
|
|
'wrap' => [
|
|
'open' => '[',
|
|
'close' => ']',
|
|
'segment_open' => '[',
|
|
'segment_close' => ']',
|
|
],
|
|
'prefix' => [ 'get_container', 'get_id', 'add_prefix' ],
|
|
'recursive' => true,
|
|
],
|
|
true
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds custom ID format.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @param string $name Format name.
|
|
* @param array $wrap
|
|
* @param array $prefix
|
|
* @param bool $recursive Optional.
|
|
* @param bool $overwrite Optional. Overwrite existing format. Default false.
|
|
* @return void
|
|
*/
|
|
protected function add_id_format( $name, array $options, $overwrite = false ) {
|
|
// Init ID formats before adding new ones.
|
|
$this->init_id_formats();
|
|
// Validate args.
|
|
$name = trim( $name );
|
|
// Stop if name invalid.
|
|
if ( empty( $name ) ) {
|
|
return;
|
|
}
|
|
$overwrite = (bool) $overwrite;
|
|
// Do not add format if name matches existing format (when overwriting not allowed).
|
|
if ( ! $overwrite && in_array( $name, array_keys( $this->id_formats ), true ) ) {
|
|
return;
|
|
}
|
|
// Normlize options.
|
|
$options = wp_parse_args(
|
|
$options,
|
|
[
|
|
'wrap' => [],
|
|
'prefix' => [],
|
|
'recursive' => false,
|
|
]
|
|
);
|
|
// Add format.
|
|
$this->id_formats[ $name ] = $options;
|
|
}
|
|
|
|
/**
|
|
* Retrieve value from data member
|
|
* @param string $context Context to format data for
|
|
* @param bool $top (optional) Whether to traverse through the field hierarchy to get data for field (Default: TRUE)
|
|
* @return mixed Value at specified path
|
|
*/
|
|
function get_data( $context = '', $top = true ) {
|
|
$opt_d = array(
|
|
'context' => '',
|
|
'top' => true,
|
|
);
|
|
$args = func_get_args();
|
|
$a = false;
|
|
if ( count( $args ) === 1 && is_array( $args[0] ) && ! empty( $args[0] ) ) {
|
|
$a = true;
|
|
$args = wp_parse_args( $args[0], $opt_d );
|
|
extract( $args );
|
|
}
|
|
|
|
if ( is_string( $top ) ) {
|
|
if ( 'false' === $top ) {
|
|
$top = false;
|
|
} elseif ( 'true' === $top ) {
|
|
$top = true;
|
|
} elseif ( is_numeric( $top ) ) {
|
|
$top = intval( $top );
|
|
}
|
|
}
|
|
$top = ! ! $top;
|
|
$obj =& $this;
|
|
$obj_path = array( $this );
|
|
$path = array();
|
|
if ( $top ) {
|
|
// Iterate through hiearchy to get top-most object
|
|
while ( ! empty( $obj ) ) {
|
|
$new = null;
|
|
// Try to get caller first
|
|
if ( method_exists( $obj, 'get_caller' ) ) {
|
|
$checked = true;
|
|
$new =& $obj->get_caller();
|
|
}
|
|
// Try to get container if no caller found
|
|
if ( empty( $new ) && method_exists( $obj, 'get_container' ) ) {
|
|
$checked = true;
|
|
$new =& $obj->get_container();
|
|
// Load data
|
|
if ( method_exists( $new, 'load_data' ) ) {
|
|
$new->load_data();
|
|
}
|
|
}
|
|
|
|
$obj =& $new;
|
|
unset( $new );
|
|
// Stop iteration
|
|
if ( ! empty( $obj ) ) {
|
|
// Add object to path if it is valid
|
|
$obj_path[] =& $obj;
|
|
}
|
|
}
|
|
unset( $obj );
|
|
}
|
|
|
|
// Check each object (starting with top-most) for matching data for current field
|
|
|
|
// Reverse array
|
|
$obj_path = array_reverse( $obj_path );
|
|
// Build path for data location
|
|
foreach ( $obj_path as $obj ) {
|
|
if ( method_exists( $obj, 'get_id' ) ) {
|
|
$path[] = $obj->get_id();
|
|
}
|
|
}
|
|
// Iterate through objects
|
|
while ( ! empty( $obj_path ) ) {
|
|
// Get next object
|
|
$obj = array_shift( $obj_path );
|
|
// Shorten path
|
|
array_shift( $path );
|
|
// Check for value in object and stop iteration if matching data found
|
|
$val = $this->get_object_value( $obj, 'data', $path, null, 'current' );
|
|
if ( ! is_null( $val ) ) {
|
|
break;
|
|
}
|
|
}
|
|
return $this->format( $val, $context );
|
|
}
|
|
|
|
/**
|
|
* Sets value in data member
|
|
* Sets value to data member itself by default
|
|
* @param mixed $value Value to set
|
|
* @param string|array $name Name of value to set (Can also be path to value)
|
|
*/
|
|
function set_data( $value, $name = '' ) {
|
|
$ref =& $this->get_path_value( 'data', $name );
|
|
$ref = $value;
|
|
}
|
|
|
|
/**
|
|
* Sets parent object of current instance
|
|
* Parent objects must be the same object type as current instance
|
|
* @uses SLB to get field type definition
|
|
* @uses SLB_Fields::has() to check if field type exists
|
|
* @uses SLB_Fields::get() to retrieve field type object reference
|
|
* @param string|object $parent Parent ID or reference
|
|
*/
|
|
function set_parent( $parent = null ) {
|
|
// Stop processing if parent empty
|
|
if ( empty( $parent ) && ! is_string( $this->parent ) ) {
|
|
return false;
|
|
}
|
|
// Parent passed as object reference wrapped in array
|
|
if ( is_array( $parent ) && isset( $parent[0] ) && is_object( $parent[0] ) ) {
|
|
$parent = $parent[0];
|
|
}
|
|
|
|
// No parent set but parent ID (previously) set in object
|
|
if ( empty( $parent ) && is_string( $this->parent ) ) {
|
|
$parent = $this->parent;
|
|
}
|
|
|
|
// Retrieve reference object if ID was supplied
|
|
if ( is_string( $parent ) ) {
|
|
$parent = trim( $parent );
|
|
// Get parent object reference
|
|
/**
|
|
* @var SLB
|
|
*/
|
|
$b = $this->get_base();
|
|
if ( ! ! $b && isset( $b->fields ) && $b->fields->has( $parent ) ) {
|
|
$parent = $b->fields->get( $parent );
|
|
}
|
|
}
|
|
|
|
// Set parent value on object
|
|
if ( is_string( $parent ) || is_object( $parent ) ) {
|
|
$this->parent = $parent;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve field type parent
|
|
* @return SLB_Field_Type Parent field
|
|
*/
|
|
function get_parent() {
|
|
return $this->parent;
|
|
}
|
|
|
|
/**
|
|
* Set object title
|
|
* @param string $title Title for object
|
|
* @param string $plural Plural form of title
|
|
*/
|
|
function set_title( $title = '' ) {
|
|
if ( is_scalar( $title ) ) {
|
|
$this->title = wp_strip_all_tags( trim( $title ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve object title
|
|
*/
|
|
function get_title() {
|
|
return $this->get_member_value( 'title', '', '', 'current' );
|
|
}
|
|
|
|
/**
|
|
* Set object description
|
|
* @param string $description Description for object
|
|
*/
|
|
function set_description( $description = '' ) {
|
|
$this->description = wp_strip_all_tags( trim( $description ) );
|
|
}
|
|
|
|
/**
|
|
* Retrieve object description
|
|
* @return string Object description
|
|
*/
|
|
function get_description() {
|
|
$dir = 'current';
|
|
return $this->get_member_value( 'description', '', '', $dir );
|
|
}
|
|
|
|
/**
|
|
* Sets multiple properties on field type at once.
|
|
*
|
|
* @param array $properties Properties to set - each element is an
|
|
* array containing the arguments to set a
|
|
* new property.
|
|
* @return void
|
|
* @todo Test refactored code.
|
|
*/
|
|
function set_properties( $properties ) {
|
|
if ( ! is_array( $properties ) ) {
|
|
return;
|
|
}
|
|
// Normalize properties
|
|
$properties = $this->remap_properties( $properties );
|
|
$properties = $this->sort_properties( $properties );
|
|
|
|
// Set Member properties.
|
|
foreach ( $properties as $prop => $val ) {
|
|
$m = 'set_' . $prop;
|
|
if ( method_exists( $this, $m ) ) {
|
|
$this->{$m}( $val );
|
|
// Remove member property from array
|
|
unset( $properties[ $prop ] );
|
|
}
|
|
unset( $m );
|
|
}
|
|
|
|
// Filter properties
|
|
$properties = $this->filter_properties( $properties );
|
|
// Set additional instance properties
|
|
foreach ( $properties as $name => $val ) {
|
|
$this->set_property( $name, $val );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remap properties based on $map
|
|
* @uses $map For determine how child properties should map to parent properties
|
|
* @uses SLB_Utlities::array_remap() to perform array remapping
|
|
* @param array $properties Associative array of properties
|
|
* @return array Remapped properties
|
|
*/
|
|
function remap_properties( $properties ) {
|
|
// Return remapped properties
|
|
return $this->util->array_remap( $properties, $this->map );
|
|
}
|
|
|
|
/**
|
|
* Sort properties based on priority
|
|
* @uses this::property_priority
|
|
* @return array Sorted priorities
|
|
*/
|
|
function sort_properties( $properties ) {
|
|
// Stop if sorting not necessary
|
|
if ( empty( $properties ) || ! is_array( $properties ) || empty( $this->property_priority ) || ! is_array( $this->property_priority ) ) {
|
|
return $properties;
|
|
}
|
|
$props = array();
|
|
foreach ( $this->property_priority as $prop ) {
|
|
if ( ! array_key_exists( $prop, $properties ) ) {
|
|
continue;
|
|
}
|
|
// Add to new array
|
|
$props[ $prop ] = $properties[ $prop ];
|
|
// Remove from old array
|
|
unset( $properties[ $prop ] );
|
|
}
|
|
// Append any remaining properties
|
|
$props = array_merge( $props, $properties );
|
|
return $props;
|
|
}
|
|
|
|
/**
|
|
* Build properties array
|
|
* @param array $props Instance properties
|
|
* @param array $signature (optional) Default properties
|
|
* @return array Normalized properties
|
|
*/
|
|
function make_properties( $props, $signature = array() ) {
|
|
$p = array();
|
|
if ( is_array( $props ) ) {
|
|
foreach ( $props as $prop ) {
|
|
if ( is_array( $prop ) ) {
|
|
$p = array_merge( $prop, $p );
|
|
}
|
|
}
|
|
}
|
|
$props = $p;
|
|
if ( is_array( $signature ) ) {
|
|
$props = array_merge( $signature, $props );
|
|
}
|
|
return $props;
|
|
}
|
|
|
|
function validate_id( $id ) {
|
|
return ( is_scalar( $id ) && ! empty( $id ) ) ? true : false;
|
|
}
|
|
|
|
function integrate_id( $id ) {
|
|
return ( $this->validate_id( $id ) ) ? array( 'id' => $id ) : array();
|
|
}
|
|
|
|
/**
|
|
* Filter property members
|
|
* @uses $property_filter to remove define members to remove from $properties
|
|
* @param array $props Properties
|
|
* @return array Filtered properties
|
|
*/
|
|
function filter_properties( $props = array() ) {
|
|
return $this->util->array_filter_keys( $props, $this->property_filter );
|
|
}
|
|
|
|
/**
|
|
* Add/Set a property on the field definition
|
|
* @param string $name Name of property
|
|
* @param mixed $value Default value for property
|
|
* @param string|array $group Group(s) property belongs to
|
|
* @return boolean TRUE if property is successfully added to field type, FALSE otherwise
|
|
*/
|
|
function set_property( $name, $value = '', $group = null ) {
|
|
// Do not add if property name is not a string
|
|
if ( ! is_string( $name ) ) {
|
|
return false;
|
|
}
|
|
// Create property array
|
|
$prop_arr = array();
|
|
$prop_arr['value'] = $value;
|
|
// Add to properties array
|
|
$this->properties[ $name ] = $value;
|
|
// Add property to specified groups
|
|
if ( ! empty( $group ) ) {
|
|
$this->set_group_property( $group, $name );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Retreives property from field type
|
|
* @param string $name Name of property to retrieve
|
|
* @return mixed Specified Property if exists (Default: Empty string)
|
|
*/
|
|
function get_property( $name ) {
|
|
$val = $this->get_member_value( 'properties', $name );
|
|
return $val;
|
|
}
|
|
|
|
/**
|
|
* Removes a property from item
|
|
* @param string $name Property ID
|
|
*/
|
|
function remove_property( $name ) {
|
|
// Remove property
|
|
if ( isset( $this->properties[ $name ] ) ) {
|
|
unset( $this->properties[ $name ] );
|
|
}
|
|
// Remove from group
|
|
foreach ( array_keys( $this->property_groups ) as $g ) {
|
|
if ( isset( $this->property_groups[ $g ][ $name ] ) ) {
|
|
unset( $this->property_groups[ $g ][ $name ] );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds Specified Property to a Group
|
|
* @param string|array $group Group(s) to add property to
|
|
* @param string $property Property to add to group
|
|
*/
|
|
function set_group_property( $group, $property ) {
|
|
if ( is_string( $group ) && isset( $this->property_groups[ $group ][ $property ] ) ) {
|
|
return;
|
|
}
|
|
if ( ! is_array( $group ) ) {
|
|
$group = array( $group );
|
|
}
|
|
|
|
foreach ( $group as $g ) {
|
|
$g = trim( $g );
|
|
// Initialize group if it doesn't already exist
|
|
if ( ! isset( $this->property_groups[ $g ] ) ) {
|
|
$this->property_groups[ $g ] = array();
|
|
}
|
|
|
|
// Add property to group
|
|
$this->property_groups[ $g ][ $property ] = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve property group
|
|
* @param string $group Group to retrieve
|
|
* @return array Array of properties in specified group
|
|
*/
|
|
function get_group( $group ) {
|
|
return $this->get_member_value( 'property_groups', $group, array() );
|
|
}
|
|
|
|
/**
|
|
* Save field data
|
|
* Child classes will define their own
|
|
* functionality for this method
|
|
* @return bool TRUE if save was successful (FALSE otherwise)
|
|
*/
|
|
function save() {
|
|
return true;
|
|
}
|
|
|
|
/*-** Hooks **-*/
|
|
|
|
/**
|
|
* Retrieve hooks added to object
|
|
* @return array Hooks
|
|
*/
|
|
function get_hooks() {
|
|
return $this->get_member_value( 'hooks', '', array() );
|
|
}
|
|
|
|
/**
|
|
* Add hook for object
|
|
* @see add_filter() for parameter defaults
|
|
* @param $tag
|
|
* @param $function_to_add
|
|
* @param $priority
|
|
* @param $accepted_args
|
|
*/
|
|
function add_hook( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
|
|
// Create new array for tag (if not already set)
|
|
if ( ! isset( $this->hooks[ $tag ] ) ) {
|
|
$this->hooks[ $tag ] = array();
|
|
}
|
|
// Build Unique ID
|
|
if ( is_string( $function_to_add ) ) {
|
|
$id = $function_to_add;
|
|
} elseif ( is_array( $function_to_add ) && ! empty( $function_to_add ) ) {
|
|
$id = strval( $function_to_add[ count( $function_to_add ) - 1 ] );
|
|
} else {
|
|
$id = 'function_' . ( count( $this->hooks[ $tag ] ) + 1 );
|
|
}
|
|
// Add hook
|
|
$this->hooks[ $tag ][ $id ] = func_get_args();
|
|
}
|
|
|
|
/**
|
|
* Convenience method for adding an action for object
|
|
* @see add_filter() for parameter defaults
|
|
* @param $tag
|
|
* @param $function_to_add
|
|
* @param $priority
|
|
* @param $accepted_args
|
|
*/
|
|
function add_action( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
|
|
$this->add_hook( $tag, $function_to_add, $priority, $accepted_args );
|
|
}
|
|
|
|
/**
|
|
* Convenience method for adding a filter for object
|
|
* @see add_filter() for parameter defaults
|
|
* @param $tag
|
|
* @param $function_to_add
|
|
* @param $priority
|
|
* @param $accepted_args
|
|
*/
|
|
function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
|
|
$this->add_hook( $tag, $function_to_add, $priority, $accepted_args );
|
|
}
|
|
|
|
/*-** Dependencies **-*/
|
|
|
|
/**
|
|
* Adds dependency to object
|
|
* @param string $type Type of dependency to add (script, style)
|
|
* @param array|string $context When dependency will be added (@see SLB_Utilities::get_action() for possible contexts)
|
|
* @see wp_enqueue_script for the following of the parameters
|
|
* @param $handle
|
|
* @param $src
|
|
* @param $deps
|
|
* @param $ver
|
|
* @param $ex
|
|
*/
|
|
function add_dependency( $type, $context, $handle, $src = false, $deps = array(), $ver = false, $ex = false ) {
|
|
$args = func_get_args();
|
|
// Remove type/context from arguments
|
|
$args = array_slice( $args, 2 );
|
|
|
|
// Set context
|
|
if ( ! is_array( $context ) ) {
|
|
// Wrap single contexts in an array
|
|
if ( is_string( $context ) ) {
|
|
$context = array( $context );
|
|
} else {
|
|
$context = array();
|
|
}
|
|
}
|
|
// Add file to instance property
|
|
if ( isset( $this->{$type} ) && is_array( $this->{$type} ) ) {
|
|
$this->{$type}[ $handle ] = array(
|
|
'context' => $context,
|
|
'params' => $args,
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add script to object to be added in specified contexts
|
|
* @param array|string $context Array of contexts to add script to page
|
|
* @see wp_enqueue_script for the following of the parameters
|
|
* @param $handle
|
|
* @param $src
|
|
* @param $deps
|
|
* @param $ver
|
|
* @param $in_footer
|
|
*/
|
|
function add_script( $context, $handle, $src = false, $deps = array(), $ver = false, $in_footer = false ) {
|
|
$args = func_get_args();
|
|
// Add file type to front of arguments array
|
|
array_unshift( $args, 'scripts' );
|
|
call_user_func_array( $this->m( 'add_dependency' ), $args );
|
|
}
|
|
|
|
/**
|
|
* Retrieve script dependencies for object
|
|
* @return array Script dependencies
|
|
*/
|
|
function get_scripts() {
|
|
return $this->get_member_value( 'scripts', '', array() );
|
|
}
|
|
|
|
/**
|
|
* Add style to object to be added in specified contexts
|
|
* @param array|string $context Array of contexts to add style to page
|
|
* @see wp_enqueue_style for the following of the parameters
|
|
* @param $handle
|
|
* @param $src
|
|
* @param $deps
|
|
* @param $ver
|
|
* @param $in_footer
|
|
*/
|
|
function add_style( $handle, $src = false, $deps = array(), $ver = false, $media = false ) {
|
|
$args = func_get_args();
|
|
array_unshift( $args, 'styles' );
|
|
call_user_func_array( $this->m( 'add_dependency' ), $args );
|
|
}
|
|
|
|
/**
|
|
* Retrieve Style dependencies for object
|
|
* @return array Style dependencies
|
|
*/
|
|
function get_styles() {
|
|
return $this->get_member_value( 'styles', '', array() );
|
|
}
|
|
|
|
/* Helpers */
|
|
|
|
/**
|
|
* Format value based on specified context
|
|
* @param mixed $value Value to format
|
|
* @param string $context Current context
|
|
* @return mixed Formatted value
|
|
*/
|
|
function format( $value, $context = '' ) {
|
|
if ( is_scalar( $context ) && ! empty( $context ) ) {
|
|
$handler = 'format_' . trim( strval( $context ) );
|
|
// Only process if context is valid and has a handler
|
|
if ( ! empty( $context ) && method_exists( $this, $handler ) ) {
|
|
// Pass value to handler
|
|
$value = $this->{$handler}( $value, $context );
|
|
}
|
|
}
|
|
// Return formatted value
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Format value for output as an attribute.
|
|
*
|
|
* Only strings are formatted.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @param mixed $value Value to format.
|
|
* @return mixed Formatted value.
|
|
*/
|
|
function format_attr( $value ) {
|
|
if ( is_string( $value ) ) {
|
|
$value = esc_attr( $value );
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Formats value for output as plain text.
|
|
*
|
|
* Escapes HTML, etc.
|
|
* Only strings are formatted.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @param mixed $value Value to format.
|
|
* @return mixed Formatted value.
|
|
*/
|
|
function format_text( $value ) {
|
|
if ( is_string( $value ) ) {
|
|
$value = esc_html( $value );
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Final formatting before output
|
|
* Restores special characters, etc.
|
|
* @uses $special_chars
|
|
* @uses $special_chars_default
|
|
* @param mixed $value Pre-final field output
|
|
* @param string $context (Optional) Formatting context
|
|
* @return mixed Formatted value
|
|
*/
|
|
function format_final( $value, $context = '' ) {
|
|
if ( ! is_string( $value ) ) {
|
|
return $value;
|
|
}
|
|
|
|
// Restore special chars
|
|
return $this->restore_special_chars( $value, $context );
|
|
}
|
|
|
|
function preserve_special_chars( $value, $context = '' ) {
|
|
if ( ! is_string( $value ) ) {
|
|
return $value;
|
|
}
|
|
$specials = $this->get_special_chars();
|
|
return str_replace( array_keys( $specials ), $specials, $value );
|
|
}
|
|
|
|
function restore_special_chars( $value, $context = '' ) {
|
|
if ( ! is_string( $value ) ) {
|
|
return $value;
|
|
}
|
|
$specials = $this->get_special_chars();
|
|
return str_replace( $specials, array_keys( $specials ), $value );
|
|
}
|
|
|
|
/**
|
|
* Retrieve special characters/placeholders
|
|
* Merges defaults with class-specific characters
|
|
* @uses $special_chars
|
|
* @uses $special_chars_default
|
|
* @return array Special characters/placeholders
|
|
*/
|
|
function get_special_chars() {
|
|
return wp_parse_args( $this->special_chars, $this->special_chars_default );
|
|
}
|
|
}
|