/** * Register the post type inside of an Item classes' on_load() method. * * @param array $args * * @link http://codex.wordpress.org/Function_Reference/register_post_type#Parameters */ static function register_post_type($args = array()) { $args = wp_parse_args($args, array('label' => WPLib_Posts::_get_post_type_label(static::POST_TYPE, 'name'), 'labels' => WPLib_Posts::_get_post_type_labels(static::POST_TYPE))); if (isset($args['taxonomies'])) { $message = 'Cannot set taxonomies via WPLib::%s(). Assign this post type via WPLib::register_taxonomy()'; WPLib::trigger_error(sprintf($message, __METHOD__)); } WPLib_Posts::_set_post_type_args(static::POST_TYPE, $args); }
/** * Returns the "current screen." * * Same as WordPress' get_current_screen() but will call set_current_screen() if is null. * * @since 0.9.9 * @return WP_Screen */ static function current_screen() { if (!function_exists('get_current_screen')) { $err_msg = __("%s() cannot be called before WordPress' get_current_screen() is loaded.", 'wplib'); WPLib::trigger_error($err_msg, __METHOD__, E_USER_ERROR); $current_screen = null; } else { if (is_null($current_screen = get_current_screen())) { /* * set_current_screen() has to be called before * get_current_screen() will return a non-null value. */ set_current_screen(); $current_screen = get_current_screen(); } } return $current_screen; }
/** * Call at the start of a method to check stability level. * * Stability levels can be one of: * * WPLib_Stability::DEPRECATED (0) * WPLib_Stability::EXPERIMENTAL (1) * WPLib_Stability::STABLE (2) * WPLib_Stability::LOCKED (3) * * @example The follow illustrates how to check that the stability * level is low enough to support EXPERIMENTAL methods. * * /** ` * * @stablity 1 - Experimental * * / * function foo() { * self::stability()->check_method( __METHOD__, WPLib_Stability::EXPERIMENTAL ); * // Do the work of foo() * return; * } * * @param string $method_name * @param int $stability */ static function check_method($method_name, $stability) { if (intval((string) WPLib::stability()) > $stability) { $err_msg = __('The %s method has been marked with a stability of %d ' . 'but the current WPLIB_STABILITY requirement is set to %d. ' . 'You can enable this in wp-config-local.php but BE AWARE that ', 'wplib'); switch ($stability) { case self::DEPRECATED: $err_msg .= __('the method has been DEPRECATED and you ' . 'should really revise your code.', 'wplib'); break; case self::EXPERIMENTAL: $err_msg .= __('the method is EXPERIMENTAL so it is likely to ' . 'change thus forcing you to modify your own code ' . 'when it changes when you plan to upgrade to a ' . 'newer version of WPLib.', 'wplib'); break; case self::STABLE: $err_msg .= __('the method is STABLE so it is unlikely to change ' . 'but it has not yet been locked to it is possible ' . 'this it could change. If so you will need to modify ' . 'your own code when you plan to upgrade to a newer ' . 'version of WPLib.', 'wplib'); break; default: $err_msg = false; break; } if ($err_msg) { $err_msg .= __(' To enable add "define( \'WPLIB_STABILITY\', %d );" to your config file.', 'wplib'); WPLib::trigger_error(sprintf($err_msg, $method_name, $stability, WPLIB_STABILITY, $stability)); } } }
/** * Return the post type as defined by the class. * * Validate against the current post if there is a current post. * * @return string|null */ function post_type() { if (!is_object($this->owner)) { $post_type = null; } else { $post_type = $this->owner->get_constant('POST_TYPE'); } if ($this->has_post() && $this->_post->post_type != $post_type) { $message = __('Post type mismatch: %s=%s, WP_Post=%s.', 'wplib'); WPLib::trigger_error(sprintf($message, get_class($this), $post_type, $this->_post->post_type)); } return $post_type; }
/** * @param array|string|WPLib_Query $query * @param array $args { * * @type string $list_class The specific class for the list, i.e. WPLib_Post_List * * @type string $default_list The default list if no $list_class, i.e. WPLib_Post_List_Default * * @type string $items The array of items, or a callable that will return a list of items. * * @type string $list_owner The class "owning" the list, typically "Owner" if Owner::get_list() * * @type string $instance_class The class for items in the list, i.e. WP_Post * } * * @return WPLib_List_Default[] * */ static function get_list($query = array(), $args = array()) { if (is_string($query)) { $query = wp_parse_args($query); } else { if (is_null($query)) { $query = array(); } } if (!isset($args['list_owner'])) { $args['list_owner'] = get_called_class(); } if (!isset($args['instance_class'])) { $args['instance_class'] = WPLib::get_constant('INSTANCE_CLASS', $args['list_owner']); } $try_class = $args['instance_class']; $args = wp_parse_args($args, array('list_class' => "{$try_class}_List", 'default_list' => 'WPLib_List_Default', 'items' => false)); if (!class_exists($args['list_class'])) { do { /** * @future Provide a more robust mechanism for discovering 'list_class' */ /* * Add '_Default' to last list class checked, * i.e. WPLib_Post_List_Default for WPLib_Posts::get_list() */ $args['list_class'] = "{$args['list_class']}_Default"; if (class_exists($args['list_class'])) { break; } $args['list_class'] = false; $try_class = preg_replace('#^(.+)_Base$#', '$1', get_parent_class($try_class)); if (!$try_class) { break; } /* * Add '_List' to element class, * i.e. WPLib_Post_List for WPLib_Posts::get_list() */ $args['list_class'] = "{$try_class}_List"; if (class_exists($args['list_class'])) { break; } } while ($try_class); } if (!$args['list_class']) { /* * Give up and use default, i.e. WPLib_List_Default */ $args['list_class'] = $args['default_list']; } $list_class = $args['list_class']; $items = is_callable($args['items']) ? call_user_func($args['items'], $query, $args) : null; if (is_null($args['instance_class'])) { $message = __('No constant %s::INSTANCE_CLASS defined.', 'wplib'); WPLib::trigger_error(sprintf($message, $args['list_owner'])); $list = array(); } else { $list = !is_null($items) ? new $list_class($items, $args) : array(); } unset($args['list_owner'], $args['list_class'], $args['list_default'], $args['default_list'], $args['items']); return $list; }
/** * @param string|object $view * @param string|object $model * @param string $method_name * @param array $args * * @return mixed */ static function do_the_methods($view, $model, $method_name, $args) { $value = null; if (preg_match('#^the_(.+)_template$#', $method_name, $match)) { /* * Put the $template name at the beginning of the $args array */ array_unshift($args, str_replace('_', '-', $match[1])); /** * Now call 'the_template' with $template as first element in $args */ $value = call_user_func_array(array($view, 'the_template'), $args); if (preg_match('#^<\\{WPLib:(.+)\\}>#', $value, $match)) { /** * Check to see if their is a content type indicator */ switch ($match[1]) { case 'JSON': $suffix = '_json'; break; case 'HTML': default: $suffix = '_html'; /* * Indicate that this content need not be run through wp_kses_post() * since it was loaded by a template which can be reviewed for security. */ $has_html_suffix = true; break; } } } else { if (method_exists($view, $method_name) && is_callable($callable = array($view, $method_name))) { /** * Call the view method directly. */ $value = call_user_func_array($callable, $args); } else { if (preg_match('#^the_(.+?)(_attr|_url|_html|_link)?$#', $method_name, $match)) { $method_name = $match[1]; $suffix = 3 == count($match) ? $match[2] : false; if (is_callable($callable = array($view, $suffix_method = "{$method_name}{$suffix}")) && method_exists($view, $suffix_method)) { /** * @note Reading this and want to know why do we use both is_callable() and method_exists()? * @see "More details" section and comments of http://jmfeurprier.com/2010/01/03/method_exists-vs-is_callable/ */ $has_html_suffix = preg_match('#^_(html|link)$#', $suffix); /* * Check $view to see if the suffixed method exist. */ $value = call_user_func_array($callable, $args); } else { if (is_callable($callable = array($model, $method_name)) && method_exists($model, $method_name)) { /* * Check $model to see if the method exist. */ $value = call_user_func_array($callable, $args); $has_html_suffix = false; } else { /* * Not found, throw an error. * $match[0] should have original $method_name */ $class_name = is_object($view) ? get_class($view) : $view; $message = sprintf(__('Method %s not found for class %s.', 'wplib'), $match[0], $class_name); WPLib::trigger_error($message, E_USER_ERROR); $has_html_suffix = false; } } } } } /** * Auto-escape output */ switch ($suffix) { case '_attr': echo $value = esc_attr($value); break; case '_url': echo $value = esc_url($value); break; case '_html': case '_link': echo $has_html_suffix ? $value : wp_kses_post($value); break; default: echo $value = esc_html($value); } }
/** * Allows a post type to attach a taxonomy that is registered by someone else's code. * * @param string $taxonomy * * @stability 1 - Experimental */ static function attach_taxonomy($taxonomy) { $VALID_HOOK = 'wplib_post_register_taxonomies'; if (current_action() !== $VALID_HOOK) { $class_name = get_called_class(); $err_msg = __('%s::%s() will only work correctly if called within the action hook %s.', 'wplib'); WPLib::trigger_error(sprintf($err_msg, $class_name, __FUNCTION__, $VALID_HOOK)); } register_taxonomy_for_object_type($taxonomy, static::POST_TYPE); }
/** * @param WPLib_Item_Base|WP_Post|WP_Term $item * @param array $args * * @return WPLib_Term_Base|WPLib_Post_Base */ static function make_new_item($item, $args = array()) { $class = get_called_class(); if (WPLib::get_constant('INSTANCE_CLASS', $class)) { if (self::class_declares_method($class, 'make_new_item')) { $item = $class::make_new_item($item, $args); } else { if (WPLib::is_development()) { $err_msg = __('Cannot make new item. Class %s does not have make_new_item method', 'wplib'); WPLib::trigger_error(sprintf($err_msg, $class), E_USER_ERROR); } } } else { if (WPLib::is_development()) { $err_msg = __('Cannot make new item. Class %s does not have INSTANCE_CLASS constant.', 'wplib'); WPLib::trigger_error(sprintf($err_msg, $class), E_USER_ERROR); } } return $item; }
/** * Generate debugging error message for attempts to call a non-existent method. * * @param string $method_name * @param array $args * * @return mixed */ function __call($method_name, $args) { $value = null; if (preg_match('#^the_#', $method_name) && is_callable(array($this, $method_name))) { $value = WPLib::do_the_methods($this, $this, $method_name, $args); } else { /* * Oops. No method was found. Output an error message. */ $message = sprintf(__('ERROR: There is no method %s() in class %s. ', 'wplib'), $method_name, get_class($this)); WPLib::trigger_error($message, E_USER_ERROR); } return $value; }
/** * Create new Instance of a Term Item * * @param WP_Term|int $term * @param array $args { * * @type string $taxonomy * @type string $instance_class * @type string $list_owner * *} * @return mixed * * @future Alias this with make_new_term() so it can be called as WPLib::make_new_term( $term_id ) */ static function make_new_item($term, $args = array()) { $args = wp_parse_args($args, array('instance_class' => false, 'taxonomy' => false, 'list_owner' => 'WPLib_Terms')); if (is_numeric($term)) { if ($args['taxonomy']) { $term = WP_Term::get_instance($term, $args['taxonomy']); } else { global $wp_version; if (version_compare($wp_version, '4.3', '<')) { /** * This only works in WordPress DBs created since 4.3+. * * @see https://make.wordpress.org/core/2015/06/09/eliminating-shared-taxonomy-terms-in-wordpress-4-3/ */ $err_msg = __("Cannot call %s() without \$args['taxonomy'] set in WordPress version 4.2 or earlier.", 'wplib'); WPLib::trigger_error($err_msg, __METHOD__); } else { $term = WP_Term::get_instance($term); } } } if (!$args['instance_class']) { $args['instance_class'] = WPLib::get_constant('INSTANCE_CLASS', $args['list_owner']); } if (!$args['instance_class']) { $args['instance_class'] = self::get_taxonomy_class($term->taxonomy); } $instance_class = $args['instance_class']; return $instance_class ? new $instance_class($term) : null; }
/** * @param WPLib_Item_Base|WP_Post|WP_Term $item * @param array $args * * @return WPLib_Term_Base|WPLib_Post_Base */ static function make_new_item($item, $args = array()) { $class = get_called_class(); if (WPLib::get_constant('POST_TYPE', $class)) { $item = WPLib_Posts::make_new_item($item, $args); } else { if (WPLib::get_constant('TAXONOMY', $class)) { $item = WPLib_Terms::make_new_item($item, $args); } else { $err_msg = __('Cannot make new item. Class %s does not have POST_TYPE or TAXONOMY constant.', 'wplib'); WPLib::trigger_error(sprintf($err_msg, $class)); } } return $item; }