Key: Property name * > Value: Required data type * @var array */ private $required = array(); /** * Default required properties * Merged into $required array with this->init_required() * @see this->required for more information * @var array */ private $_required = array( 'id' => 'string', 'labels' => 'array', ); /* Init */ /** * Constructor * @return obj Current instance */ public function __construct( $id, $labels, $callback = null, $capability = null, $icon = null ) { $props = array( 'labels' => $labels, 'callback' => $callback, 'capability' => $capability, 'icon' => $icon, ); parent::__construct( $id, $props ); $this->init_required(); return $this; } protected function init_required() { $this->required = array_merge( $this->_required, $this->required ); // Check for parent requirement if ( $this->parent_required ) { $this->required['parent'] = 'string'; } } /** * Set required feature * @param string $feature Required feature */ protected function _require( $feature ) { if ( ! isset( $this->_required[ $feature ] ) ) { $this->_required[ $feature ] = true; } return $this; } /** * Check if feature is required * @param string $feature Feature to check for * @return bool TRUE if feature required */ protected function _is_required( $feature ) { return ( isset( $this->_required[ $feature ] ) ) ? true : false; } /* Property Methods */ /** * Retrieve ID (Formatted by default) * @param bool $formatted (optional) Whether ID should be formatted for external use or not * @return string ID */ public function get_id( $formatted = true ) { $id = parent::get_id(); if ( $formatted ) { $this->add_prefix_ref( $id ); } return $id; } /** * Retrieve raw ID * @return string Raw ID */ public function get_id_raw() { return $this->get_id( false ); } /** * Retrieve label * Uses first label (or default if defined) if specified type does not exist * @param string $type Label type to retrieve * @param string $default (optional) Default value if label type does not exist * @return string Label text */ public function get_label( $type, $default = null ) { // Retrieve existing label type if ( $this->has_label( $type ) ) { return $this->labels[ $type ]; } // Use default label if type is not set if ( empty( $default ) && ! empty( $this->labels ) ) { reset( $this->labels ); $default = current( $this->labels ); } return ( empty( $default ) ) ? '' : $default; } /** * Set text labels * @param array|string $labels * @return obj Current instance */ public function set_labels( $labels ) { if ( empty( $labels ) ) { return this; } // Single string if ( is_string( $labels ) ) { $labels = array( $labels ); } // Array if ( is_array( $labels ) ) { // Merge with existing labels if ( empty( $this->labels ) || ! is_array( $this->labels ) ) { $this->labels = array(); } $this->labels = array_merge( $this->labels, $labels ); } return $this; } /** * Set single text label * @uses this->set_labels() * @param string $type Label type to set * @param string $value Label value * @return obj Current instance */ public function set_label( $type, $value ) { if ( is_string( $type ) && is_string( $value ) ) { $label = array( $type => $value ); $this->set_labels( $label ); } return $this; } /** * Checks if specified label is set on view * @param string $type Label type * @return bool TRUE if label exists, FALSE otherwise */ public function has_label( $type ) { return ( isset( $this->labels[ $type ] ) ); } /* Content */ /** * Add content block to view * Child classes define method functionality * @param string $id Content block ID * @param array $args Content arguments (Defined by child class), converted to an object * @return obj Current View instance */ public function add_content( $id, $args ) { // Save parameters $this->content_raw[ $id ] = (object) $args; // Clear parsed content $this->content = array(); // Return instance reference return $this; } /** * Retrieve content */ protected function get_content( $parsed = true ) { // Return raw content. if ( ! $parsed ) { return $this->content_raw; } // Return parsed content. if ( empty( $this->content ) && ! empty( $this->content_raw ) ) { $this->content = $this->parse_content(); } return $this->content; } /** * Parse content * Child classes define functionality * @return array Parsed content */ protected function parse_content() { return $this->get_content( false ); } /** * Check if content has been added to view * @return bool TRUE if content added */ protected function has_content() { $raw = $this->get_content( false ); return ! empty( $raw ); } /** * Render content */ protected function render_content( $context = 'default' ) {} /** * Retrieve view messages * @return array Messages */ protected function &get_messages() { if ( ! is_array( $this->messages ) ) { $this->messages = array(); } return $this->messages; } /** * Save message * @param string $text Message text * @return obj Current instance */ public function set_message( $text ) { $msgs =& $this->get_messages(); $text = trim( $text ); if ( empty( $msgs ) && ! empty( $text ) ) { $this->util->add_filter( 'admin_messages', $this->m( 'do_messages' ), 10, 1, false ); } $msgs[] = $text; return $this; } /** * Add messages to array * Called by internal `admin_messages` filter hook * @param array $msgs Aggregated messages * @return array Merged messages array */ public function do_messages( $msgs = array() ) { $m =& $this->get_messages(); if ( ! empty( $m ) ) { $msgs = array_merge( $msgs, $m ); } return $msgs; } /** * Retrieve view callback * @return callback Callback (Default: standard handler method) */ public function get_callback() { return ( $this->has_callback() ) ? $this->callback : $this->m( 'handle' ); } /** * Set callback function for building item * @param callback $callback Callback function to use * @return obj Current instance */ public function set_callback( $callback ) { $this->callback = ( is_callable( $callback ) ) ? $callback : null; return $this; } /** * Check if callback set * @return bool TRUE if callback is set */ protected function has_callback() { return ( ! empty( $this->callback ) ) ? true : false; } /** * Run callback */ public function do_callback() { call_user_func( $this->get_callback() ); } /** * Retrieve capability * @return string Capability */ public function get_capability() { return $this->capability; } /** * Set capability for access control * @param string $capability Capability * @return obj Current instance */ public function set_capability( $capability ) { if ( is_string( $capability ) && ! empty( $capability ) ) { $this->capability = $capability; } return $this; } /** * Set icon * @param string $icon Icon URI * @return obj Current instance */ public function set_icon( $icon ) { if ( ! empty( $icon ) && is_string( $icon ) ) { $this->icon = $icon; } return $this; } protected function get_hookname() { return ( empty( $this->hookname ) ) ? '' : $this->hookname; } /** * Set hookname * @param string $hookname Hookname value * @return obj Current instance */ public function set_hookname( $hookname ) { if ( ! empty( $hookname ) && is_string( $hookname ) ) { $this->hookname = $hookname; } return $this; } /** * Retrieve parent * Formats parent ID for custom parents * @uses parent::get_parent() * @return string Parent ID */ public function get_parent() { $parent = parent::get_parent(); return ( $this->is_parent_custom() ) ? $this->add_prefix( $parent ) : $parent; } /** * Set parent for view * @param string $parent Parent ID * @return obj Current instance */ public function set_parent( $parent ) { if ( $this->parent_required ) { if ( ! empty( $parent ) && is_string( $parent ) ) { $this->parent = $parent; } } else { $this->parent = null; } return $this; } /** * Specify whether parent is a custom view or a WP view * @param bool $custom (optional) TRUE if custom, FALSE if WP * @return obj Current instance */ protected function set_parent_custom( $custom = true ) { if ( $this->parent_required ) { $this->parent_custom = ! ! $custom; } return $this; } /** * Set parent as WP view * @uses this->set_parent_custom() * @return obj Current instance */ public function set_parent_wp() { $this->set_parent_custom( false ); return $this; } /** * Get view URI * URI Structures: * > Top Level Menus: admin.php?page={menu_id} * > Pages: [parent_page_file.php|admin.php]?page={page_id} * > Section: [parent_menu_uri]#{section_id} * * @uses $admin_page_hooks to determine if page is child of default WP page * @param string $file (optional) Base file name * @param string $format (optional) Format string for URI * @return string Object URI */ public function get_uri( $file = null, $format = null ) { static $page_hooks = null; $uri = ''; if ( empty( $file ) ) { $file = 'admin.php'; } if ( $this->is_child() ) { $parent = str_replace( '_page_' . $this->get_id(), '', $this->get_hookname() ); if ( is_null( $page_hooks ) ) { $page_hooks = array_flip( $GLOBALS['admin_page_hooks'] ); } if ( isset( $page_hooks[ $parent ] ) ) { $file = $page_hooks[ $parent ]; } } if ( empty( $format ) ) { $delim = ( strpos( $file, '?' ) === false ) ? '?' : '&'; $format = '%1$s' . $delim . 'page=%2$s'; } $uri = sprintf( $format, $file, $this->get_id() ); return $uri; } /* Handlers */ /** * Default View handler * Used as callback when none set */ public function handle() {} /* Validation */ /** * Check if instance is valid based on required properties/data types * @return bool TRUE if valid, FALSE if not valid */ public function is_valid() { $invalid = false; foreach ( $this->required as $prop => $type ) { // Baseline validation. if ( empty( $this->{$prop} ) || empty( $type ) || ! is_string( $type ) ) { return $invalid; } // Validate data type. $f = 'is_' . $type; if ( ! function_exists( $f ) || ! $f( $this->{$prop} ) ) { return $invalid; } } return true; } protected function is_child() { return $this->parent_required; } protected function is_parent_custom() { return ( $this->is_child() && $this->parent_custom ) ? true : false; } public function is_parent_wp() { return ( $this->is_child() && ! $this->parent_custom ) ? true : false; } }