/** * The WordPress version string * * @global string $wp_version */ $wp_version = '4.7.10'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * * @global int $wp_db_version */ $wp_db_version = 38590; /** * Holds the TinyMCE version * * @global string $tinymce_version */ $tinymce_version = '4506-20170408'; /** * Holds the required PHP version * * @global string $required_php_version */ $required_php_version = '5.2.4'; /** * Holds the required MySQL version * * @global string $required_mysql_version */ $required_mysql_version = '5.0'; /** * Core User Role & Capabilities API * * @package WordPress * @subpackage Users */ /** * Map meta capabilities to primitive capabilities. * * This does not actually compare whether the user ID has the actual capability, * just what the capability or capabilities are. Meta capability list value can * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post', * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'. * * @since 2.0.0 * * @global array $post_type_meta_caps Used to get post type meta capabilities. * * @param string $cap Capability name. * @param int $user_id User ID. * @param int $object_id Optional. ID of the specific object to check against if `$cap` is a "meta" cap. * "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used * by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts', * 'edit_others_posts', etc. The parameter is accessed via func_get_args(). * @return array Actual capabilities for meta capability. */ function map_meta_cap( $cap, $user_id ) { $args = array_slice( func_get_args(), 2 ); $caps = array(); switch ( $cap ) { case 'remove_user': $caps[] = 'remove_users'; break; case 'promote_user': case 'add_users': $caps[] = 'promote_users'; break; case 'edit_user': case 'edit_users': // Allow user to edit itself if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] ) break; // In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin. if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) { $caps[] = 'do_not_allow'; } else { $caps[] = 'edit_users'; // edit_user maps to edit_users. } break; case 'delete_post': case 'delete_page': $post = get_post( $args[0] ); if ( ! $post ) { $caps[] = 'do_not_allow'; break; } if ( 'revision' == $post->post_type ) { $post = get_post( $post->post_parent ); if ( ! $post ) { $caps[] = 'do_not_allow'; break; } } if ( ( get_option( 'page_for_posts' ) == $post->ID ) || ( get_option( 'page_on_front' ) == $post->ID ) ) { $caps[] = 'manage_options'; break; } $post_type = get_post_type_object( $post->post_type ); if ( ! $post_type ) { /* translators: 1: post type, 2: capability name */ _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); $caps[] = 'edit_others_posts'; break; } if ( ! $post_type->map_meta_cap ) { $caps[] = $post_type->cap->$cap; // Prior to 3.1 we would re-call map_meta_cap here. if ( 'delete_post' == $cap ) $cap = $post_type->cap->$cap; break; } // If the post author is set and the user is the author... if ( $post->post_author && $user_id == $post->post_author ) { // If the post is published or scheduled... if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->delete_published_posts; } elseif ( 'trash' == $post->post_status ) { $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); if ( in_array( $status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->delete_published_posts; } else { $caps[] = $post_type->cap->delete_posts; } } else { // If the post is draft... $caps[] = $post_type->cap->delete_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->delete_others_posts; // The post is published or scheduled, extra cap required. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->delete_published_posts; } elseif ( 'private' == $post->post_status ) { $caps[] = $post_type->cap->delete_private_posts; } } break; // edit_post breaks down to edit_posts, edit_published_posts, or // edit_others_posts case 'edit_post': case 'edit_page': $post = get_post( $args[0] ); if ( ! $post ) { $caps[] = 'do_not_allow'; break; } if ( 'revision' == $post->post_type ) { $post = get_post( $post->post_parent ); if ( ! $post ) { $caps[] = 'do_not_allow'; break; } } $post_type = get_post_type_object( $post->post_type ); if ( ! $post_type ) { /* translators: 1: post type, 2: capability name */ _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); $caps[] = 'edit_others_posts'; break; } if ( ! $post_type->map_meta_cap ) { $caps[] = $post_type->cap->$cap; // Prior to 3.1 we would re-call map_meta_cap here. if ( 'edit_post' == $cap ) $cap = $post_type->cap->$cap; break; } // If the post author is set and the user is the author... if ( $post->post_author && $user_id == $post->post_author ) { // If the post is published or scheduled... if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->edit_published_posts; } elseif ( 'trash' == $post->post_status ) { $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); if ( in_array( $status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->edit_published_posts; } else { $caps[] = $post_type->cap->edit_posts; } } else { // If the post is draft... $caps[] = $post_type->cap->edit_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->edit_others_posts; // The post is published or scheduled, extra cap required. if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->edit_published_posts; } elseif ( 'private' == $post->post_status ) { $caps[] = $post_type->cap->edit_private_posts; } } break; case 'read_post': case 'read_page': $post = get_post( $args[0] ); if ( ! $post ) { $caps[] = 'do_not_allow'; break; } if ( 'revision' == $post->post_type ) { $post = get_post( $post->post_parent ); if ( ! $post ) { $caps[] = 'do_not_allow'; break; } } $post_type = get_post_type_object( $post->post_type ); if ( ! $post_type ) { /* translators: 1: post type, 2: capability name */ _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); $caps[] = 'edit_others_posts'; break; } if ( ! $post_type->map_meta_cap ) { $caps[] = $post_type->cap->$cap; // Prior to 3.1 we would re-call map_meta_cap here. if ( 'read_post' == $cap ) $cap = $post_type->cap->$cap; break; } $status_obj = get_post_status_object( $post->post_status ); if ( $status_obj->public ) { $caps[] = $post_type->cap->read; break; } if ( $post->post_author && $user_id == $post->post_author ) { $caps[] = $post_type->cap->read; } elseif ( $status_obj->private ) { $caps[] = $post_type->cap->read_private_posts; } else { $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); } break; case 'publish_post': $post = get_post( $args[0] ); if ( ! $post ) { $caps[] = 'do_not_allow'; break; } $post_type = get_post_type_object( $post->post_type ); if ( ! $post_type ) { /* translators: 1: post type, 2: capability name */ _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' ); $caps[] = 'edit_others_posts'; break; } $caps[] = $post_type->cap->publish_posts; break; case 'edit_post_meta': case 'delete_post_meta': case 'add_post_meta': case 'edit_comment_meta': case 'delete_comment_meta': case 'add_comment_meta': case 'edit_term_meta': case 'delete_term_meta': case 'add_term_meta': case 'edit_user_meta': case 'delete_user_meta': case 'add_user_meta': list( $_, $object_type, $_ ) = explode( '_', $cap ); $object_id = (int) $args[0]; switch ( $object_type ) { case 'post': $post = get_post( $object_id ); if ( ! $post ) { break; } $sub_type = get_post_type( $post ); break; case 'comment': $comment = get_comment( $object_id ); if ( ! $comment ) { break; } $sub_type = empty( $comment->comment_type ) ? 'comment' : $comment->comment_type; break; case 'term': $term = get_term( $object_id ); if ( ! $term ) { break; } $sub_type = $term->taxonomy; break; case 'user': $user = get_user_by( 'id', $object_id ); if ( ! $user ) { break; } $sub_type = 'user'; break; } if ( empty( $sub_type ) ) { $caps[] = 'do_not_allow'; break; } $caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id ); $meta_key = isset( $args[1] ) ? $args[1] : false; $has_filter = has_filter( "auth_{$object_type}_meta_{$meta_key}" ) || has_filter( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}" ); if ( $meta_key && $has_filter ) { /** This filter is documented in wp-includes/meta.php */ $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", false, $meta_key, $object_id, $user_id, $cap, $caps ); /** This filter is documented in wp-includes/meta.php */ $allowed = apply_filters( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps ); if ( ! $allowed ) { $caps[] = $cap; } } elseif ( $meta_key && is_protected_meta( $meta_key, $object_type ) ) { $caps[] = $cap; } break; case 'edit_comment': $comment = get_comment( $args[0] ); if ( ! $comment ) { $caps[] = 'do_not_allow'; break; } $post = get_post( $comment->comment_post_ID ); /* * If the post doesn't exist, we have an orphaned comment. * Fall back to the edit_posts capability, instead. */ if ( $post ) { $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); } else { $caps = map_meta_cap( 'edit_posts', $user_id ); } break; case 'unfiltered_upload': if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) ) ) $caps[] = $cap; else $caps[] = 'do_not_allow'; break; case 'edit_css' : case 'unfiltered_html' : // Disallow unfiltered_html for all users, even admins and super admins. if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) $caps[] = 'do_not_allow'; elseif ( is_multisite() && ! is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = 'unfiltered_html'; break; case 'edit_files': case 'edit_plugins': case 'edit_themes': // Disallow the file editors. if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) $caps[] = 'do_not_allow'; elseif ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) $caps[] = 'do_not_allow'; elseif ( is_multisite() && ! is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = $cap; break; case 'update_plugins': case 'delete_plugins': case 'install_plugins': case 'upload_plugins': case 'update_themes': case 'delete_themes': case 'install_themes': case 'upload_themes': case 'update_core': // Disallow anything that creates, deletes, or updates core, plugin, or theme files. // Files in uploads are excepted. if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) { $caps[] = 'do_not_allow'; } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) { $caps[] = 'do_not_allow'; } elseif ( 'upload_themes' === $cap ) { $caps[] = 'install_themes'; } elseif ( 'upload_plugins' === $cap ) { $caps[] = 'install_plugins'; } else { $caps[] = $cap; } break; case 'activate_plugins': $caps[] = $cap; if ( is_multisite() ) { // update_, install_, and delete_ are handled above with is_super_admin(). $menu_perms = get_site_option( 'menu_items', array() ); if ( empty( $menu_perms['plugins'] ) ) $caps[] = 'manage_network_plugins'; } break; case 'delete_user': case 'delete_users': // If multisite only super admins can delete users. if ( is_multisite() && ! is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = 'delete_users'; // delete_user maps to delete_users. break; case 'create_users': if ( !is_multisite() ) $caps[] = $cap; elseif ( is_super_admin( $user_id ) || get_site_option( 'add_new_users' ) ) $caps[] = $cap; else $caps[] = 'do_not_allow'; break; case 'manage_links' : if ( get_option( 'link_manager_enabled' ) ) $caps[] = $cap; else $caps[] = 'do_not_allow'; break; case 'customize' : $caps[] = 'edit_theme_options'; break; case 'delete_site': $caps[] = 'manage_options'; break; case 'edit_term': case 'delete_term': case 'assign_term': $term_id = (int) $args[0]; $term = get_term( $term_id ); if ( ! $term || is_wp_error( $term ) ) { $caps[] = 'do_not_allow'; break; } $tax = get_taxonomy( $term->taxonomy ); if ( ! $tax ) { $caps[] = 'do_not_allow'; break; } if ( 'delete_term' === $cap && ( $term->term_id == get_option( 'default_' . $term->taxonomy ) ) ) { $caps[] = 'do_not_allow'; break; } $taxo_cap = $cap . 's'; $caps = map_meta_cap( $tax->cap->$taxo_cap, $user_id, $term_id ); break; case 'manage_post_tags': case 'edit_categories': case 'edit_post_tags': case 'delete_categories': case 'delete_post_tags': $caps[] = 'manage_categories'; break; case 'assign_categories': case 'assign_post_tags': $caps[] = 'edit_posts'; break; case 'create_sites': case 'delete_sites': case 'manage_network': case 'manage_sites': case 'manage_network_users': case 'manage_network_plugins': case 'manage_network_themes': case 'manage_network_options': $caps[] = $cap; break; default: // Handle meta capabilities for custom post types. global $post_type_meta_caps; if ( isset( $post_type_meta_caps[ $cap ] ) ) { $args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args ); return call_user_func_array( 'map_meta_cap', $args ); } // If no meta caps match, return the original cap. $caps[] = $cap; } /** * Filters a user's capabilities depending on specific context and/or privilege. * * @since 2.8.0 * * @param array $caps Returns the user's actual capabilities. * @param string $cap Capability name. * @param int $user_id The user ID. * @param array $args Adds the context to the cap. Typically the object ID. */ return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args ); } /** * Whether the current user has a specific capability. * * While checking against particular roles in place of a capability is supported * in part, this practice is discouraged as it may produce unreliable results. * * Note: Will always return true if the current user is a super admin, unless specifically denied. * * @since 2.0.0 * * @see WP_User::has_cap() * @see map_meta_cap() * * @param string $capability Capability name. * @param int $object_id Optional. ID of the specific object to check against if `$capability` is a "meta" cap. * "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used * by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts', * 'edit_others_posts', etc. Accessed via func_get_args() and passed to WP_User::has_cap(), * then map_meta_cap(). * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is * passed, whether the current user has the given meta capability for the given object. */ function current_user_can( $capability ) { $current_user = wp_get_current_user(); if ( empty( $current_user ) ) return false; $args = array_slice( func_get_args(), 1 ); $args = array_merge( array( $capability ), $args ); return call_user_func_array( array( $current_user, 'has_cap' ), $args ); } /** * Whether current user has a capability or role for a given site. * * @since 3.0.0 * * @param int $blog_id Site ID. * @param string $capability Capability or role name. * @return bool */ function current_user_can_for_blog( $blog_id, $capability ) { $switched = is_multisite() ? switch_to_blog( $blog_id ) : false; $current_user = wp_get_current_user(); if ( empty( $current_user ) ) { if ( $switched ) { restore_current_blog(); } return false; } $args = array_slice( func_get_args(), 2 ); $args = array_merge( array( $capability ), $args ); $can = call_user_func_array( array( $current_user, 'has_cap' ), $args ); if ( $switched ) { restore_current_blog(); } return $can; } /** * Whether author of supplied post has capability or role. * * @since 2.9.0 * * @param int|object $post Post ID or post object. * @param string $capability Capability or role name. * @return bool */ function author_can( $post, $capability ) { if ( !$post = get_post($post) ) return false; $author = get_userdata( $post->post_author ); if ( ! $author ) return false; $args = array_slice( func_get_args(), 2 ); $args = array_merge( array( $capability ), $args ); return call_user_func_array( array( $author, 'has_cap' ), $args ); } /** * Whether a particular user has capability or role. * * @since 3.1.0 * * @param int|object $user User ID or object. * @param string $capability Capability or role name. * @return bool */ function user_can( $user, $capability ) { if ( ! is_object( $user ) ) $user = get_userdata( $user ); if ( ! $user || ! $user->exists() ) return false; $args = array_slice( func_get_args(), 2 ); $args = array_merge( array( $capability ), $args ); return call_user_func_array( array( $user, 'has_cap' ), $args ); } /** * Retrieves the global WP_Roles instance and instantiates it if necessary. * * @since 4.3.0 * * @global WP_Roles $wp_roles WP_Roles global instance. * * @return WP_Roles WP_Roles global instance if not already instantiated. */ function wp_roles() { global $wp_roles; if ( ! isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); } return $wp_roles; } /** * Retrieve role object. * * @since 2.0.0 * * @param string $role Role name. * @return WP_Role|null WP_Role object if found, null if the role does not exist. */ function get_role( $role ) { return wp_roles()->get_role( $role ); } /** * Add role, if it does not exist. * * @since 2.0.0 * * @param string $role Role name. * @param string $display_name Display name for role. * @param array $capabilities List of capabilities, e.g. array( 'edit_posts' => true, 'delete_posts' => false ); * @return WP_Role|null WP_Role object if role is added, null if already exists. */ function add_role( $role, $display_name, $capabilities = array() ) { if ( empty( $role ) ) { return; } return wp_roles()->add_role( $role, $display_name, $capabilities ); } /** * Remove role, if it exists. * * @since 2.0.0 * * @param string $role Role name. */ function remove_role( $role ) { wp_roles()->remove_role( $role ); } /** * Retrieve a list of super admins. * * @since 3.0.0 * * @global array $super_admins * * @return array List of super admin logins */ function get_super_admins() { global $super_admins; if ( isset($super_admins) ) return $super_admins; else return get_site_option( 'site_admins', array('admin') ); } /** * Determine if user is a site admin. * * @since 3.0.0 * * @param int $user_id (Optional) The ID of a user. Defaults to the current user. * @return bool True if the user is a site admin. */ function is_super_admin( $user_id = false ) { if ( ! $user_id || $user_id == get_current_user_id() ) $user = wp_get_current_user(); else $user = get_userdata( $user_id ); if ( ! $user || ! $user->exists() ) return false; if ( is_multisite() ) { $super_admins = get_super_admins(); if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) ) return true; } else { if ( $user->has_cap('delete_users') ) return true; } return false; } /** * Grants Super Admin privileges. * * @since 3.0.0 * * @global array $super_admins * * @param int $user_id ID of the user to be granted Super Admin privileges. * @return bool True on success, false on failure. This can fail when the user is * already a super admin or when the `$super_admins` global is defined. */ function grant_super_admin( $user_id ) { // If global super_admins override is defined, there is nothing to do here. if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) { return false; } /** * Fires before the user is granted Super Admin privileges. * * @since 3.0.0 * * @param int $user_id ID of the user that is about to be granted Super Admin privileges. */ do_action( 'grant_super_admin', $user_id ); // Directly fetch site_admins instead of using get_super_admins() $super_admins = get_site_option( 'site_admins', array( 'admin' ) ); $user = get_userdata( $user_id ); if ( $user && ! in_array( $user->user_login, $super_admins ) ) { $super_admins[] = $user->user_login; update_site_option( 'site_admins' , $super_admins ); /** * Fires after the user is granted Super Admin privileges. * * @since 3.0.0 * * @param int $user_id ID of the user that was granted Super Admin privileges. */ do_action( 'granted_super_admin', $user_id ); return true; } return false; } /** * Revokes Super Admin privileges. * * @since 3.0.0 * * @global array $super_admins * * @param int $user_id ID of the user Super Admin privileges to be revoked from. * @return bool True on success, false on failure. This can fail when the user's email * is the network admin email or when the `$super_admins` global is defined. */ function revoke_super_admin( $user_id ) { // If global super_admins override is defined, there is nothing to do here. if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) { return false; } /** * Fires before the user's Super Admin privileges are revoked. * * @since 3.0.0 * * @param int $user_id ID of the user Super Admin privileges are being revoked from. */ do_action( 'revoke_super_admin', $user_id ); // Directly fetch site_admins instead of using get_super_admins() $super_admins = get_site_option( 'site_admins', array( 'admin' ) ); $user = get_userdata( $user_id ); if ( $user && 0 !== strcasecmp( $user->user_email, get_site_option( 'admin_email' ) ) ) { if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) { unset( $super_admins[$key] ); update_site_option( 'site_admins', $super_admins ); /** * Fires after the user's Super Admin privileges are revoked. * * @since 3.0.0 * * @param int $user_id ID of the user Super Admin privileges were revoked from. */ do_action( 'revoked_super_admin', $user_id ); return true; } } return false; } /** * User API: WP_Role class * * @package WordPress * @subpackage Users * @since 4.4.0 */ /** * Core class used to extend the user roles API. * * @since 2.0.0 */ class WP_Role { /** * Role name. * * @since 2.0.0 * @access public * @var string */ public $name; /** * List of capabilities the role contains. * * @since 2.0.0 * @access public * @var array */ public $capabilities; /** * Constructor - Set up object properties. * * The list of capabilities, must have the key as the name of the capability * and the value a boolean of whether it is granted to the role. * * @since 2.0.0 * @access public * * @param string $role Role name. * @param array $capabilities List of capabilities. */ public function __construct( $role, $capabilities ) { $this->name = $role; $this->capabilities = $capabilities; } /** * Assign role a capability. * * @since 2.0.0 * @access public * * @param string $cap Capability name. * @param bool $grant Whether role has capability privilege. */ public function add_cap( $cap, $grant = true ) { $this->capabilities[$cap] = $grant; wp_roles()->add_cap( $this->name, $cap, $grant ); } /** * Removes a capability from a role. * * This is a container for WP_Roles::remove_cap() to remove the * capability from the role. That is to say, that WP_Roles::remove_cap() * implements the functionality, but it also makes sense to use this class, * because you don't need to enter the role name. * * @since 2.0.0 * @access public * * @param string $cap Capability name. */ public function remove_cap( $cap ) { unset( $this->capabilities[$cap] ); wp_roles()->remove_cap( $this->name, $cap ); } /** * Determines whether the role has the given capability. * * The capabilities is passed through the {@see 'role_has_cap'} filter. * The first parameter for the hook is the list of capabilities the class * has assigned. The second parameter is the capability name to look for. * The third and final parameter for the hook is the role name. * * @since 2.0.0 * @access public * * @param string $cap Capability name. * @return bool True if the role has the given capability. False otherwise. */ public function has_cap( $cap ) { /** * Filters which capabilities a role has. * * @since 2.0.0 * * @param array $capabilities Array of role capabilities. * @param string $cap Capability name. * @param string $name Role name. */ $capabilities = apply_filters( 'role_has_cap', $this->capabilities, $cap, $this->name ); if ( !empty( $capabilities[$cap] ) ) return $capabilities[$cap]; else return false; } } /** * Query API: WP_Query class * * @package WordPress * @subpackage Query * @since 4.7.0 */ /** * The WordPress Query class. * * @link https://codex.wordpress.org/Function_Reference/WP_Query Codex page. * * @since 1.5.0 * @since 4.5.0 Removed the `$comments_popup` property. */ class WP_Query { /** * Query vars set by the user * * @since 1.5.0 * @access public * @var array */ public $query; /** * Query vars, after parsing * * @since 1.5.0 * @access public * @var array */ public $query_vars = array(); /** * Taxonomy query, as passed to get_tax_sql() * * @since 3.1.0 * @access public * @var object WP_Tax_Query */ public $tax_query; /** * Metadata query container * * @since 3.2.0 * @access public * @var object WP_Meta_Query */ public $meta_query = false; /** * Date query container * * @since 3.7.0 * @access public * @var object WP_Date_Query */ public $date_query = false; /** * Holds the data for a single object that is queried. * * Holds the contents of a post, page, category, attachment. * * @since 1.5.0 * @access public * @var object|array */ public $queried_object; /** * The ID of the queried object. * * @since 1.5.0 * @access public * @var int */ public $queried_object_id; /** * Get post database query. * * @since 2.0.1 * @access public * @var string */ public $request; /** * List of posts. * * @since 1.5.0 * @access public * @var array */ public $posts; /** * The amount of posts for the current query. * * @since 1.5.0 * @access public * @var int */ public $post_count = 0; /** * Index of the current item in the loop. * * @since 1.5.0 * @access public * @var int */ public $current_post = -1; /** * Whether the loop has started and the caller is in the loop. * * @since 2.0.0 * @access public * @var bool */ public $in_the_loop = false; /** * The current post. * * @since 1.5.0 * @access public * @var WP_Post */ public $post; /** * The list of comments for current post. * * @since 2.2.0 * @access public * @var array */ public $comments; /** * The amount of comments for the posts. * * @since 2.2.0 * @access public * @var int */ public $comment_count = 0; /** * The index of the comment in the comment loop. * * @since 2.2.0 * @access public * @var int */ public $current_comment = -1; /** * Current comment ID. * * @since 2.2.0 * @access public * @var int */ public $comment; /** * The amount of found posts for the current query. * * If limit clause was not used, equals $post_count. * * @since 2.1.0 * @access public * @var int */ public $found_posts = 0; /** * The amount of pages. * * @since 2.1.0 * @access public * @var int */ public $max_num_pages = 0; /** * The amount of comment pages. * * @since 2.7.0 * @access public * @var int */ public $max_num_comment_pages = 0; /** * Set if query is single post. * * @since 1.5.0 * @access public * @var bool */ public $is_single = false; /** * Set if query is preview of blog. * * @since 2.0.0 * @access public * @var bool */ public $is_preview = false; /** * Set if query returns a page. * * @since 1.5.0 * @access public * @var bool */ public $is_page = false; /** * Set if query is an archive list. * * @since 1.5.0 * @access public * @var bool */ public $is_archive = false; /** * Set if query is part of a date. * * @since 1.5.0 * @access public * @var bool */ public $is_date = false; /** * Set if query contains a year. * * @since 1.5.0 * @access public * @var bool */ public $is_year = false; /** * Set if query contains a month. * * @since 1.5.0 * @access public * @var bool */ public $is_month = false; /** * Set if query contains a day. * * @since 1.5.0 * @access public * @var bool */ public $is_day = false; /** * Set if query contains time. * * @since 1.5.0 * @access public * @var bool */ public $is_time = false; /** * Set if query contains an author. * * @since 1.5.0 * @access public * @var bool */ public $is_author = false; /** * Set if query contains category. * * @since 1.5.0 * @access public * @var bool */ public $is_category = false; /** * Set if query contains tag. * * @since 2.3.0 * @access public * @var bool */ public $is_tag = false; /** * Set if query contains taxonomy. * * @since 2.5.0 * @access public * @var bool */ public $is_tax = false; /** * Set if query was part of a search result. * * @since 1.5.0 * @access public * @var bool */ public $is_search = false; /** * Set if query is feed display. * * @since 1.5.0 * @access public * @var bool */ public $is_feed = false; /** * Set if query is comment feed display. * * @since 2.2.0 * @access public * @var bool */ public $is_comment_feed = false; /** * Set if query is trackback. * * @since 1.5.0 * @access public * @var bool */ public $is_trackback = false; /** * Set if query is blog homepage. * * @since 1.5.0 * @access public * @var bool */ public $is_home = false; /** * Set if query couldn't found anything. * * @since 1.5.0 * @access public * @var bool */ public $is_404 = false; /** * Set if query is embed. * * @since 4.4.0 * @access public * @var bool */ public $is_embed = false; /** * Set if query is paged * * @since 1.5.0 * @access public * @var bool */ public $is_paged = false; /** * Set if query is part of administration page. * * @since 1.5.0 * @access public * @var bool */ public $is_admin = false; /** * Set if query is an attachment. * * @since 2.0.0 * @access public * @var bool */ public $is_attachment = false; /** * Set if is single, is a page, or is an attachment. * * @since 2.1.0 * @access public * @var bool */ public $is_singular = false; /** * Set if query is for robots. * * @since 2.1.0 * @access public * @var bool */ public $is_robots = false; /** * Set if query contains posts. * * Basically, the homepage if the option isn't set for the static homepage. * * @since 2.1.0 * @access public * @var bool */ public $is_posts_page = false; /** * Set if query is for a post type archive. * * @since 3.1.0 * @access public * @var bool */ public $is_post_type_archive = false; /** * Stores the ->query_vars state like md5(serialize( $this->query_vars ) ) so we know * whether we have to re-parse because something has changed * * @since 3.1.0 * @access private * @var bool|string */ private $query_vars_hash = false; /** * Whether query vars have changed since the initial parse_query() call. Used to catch modifications to query vars made * via pre_get_posts hooks. * * @since 3.1.1 * @access private */ private $query_vars_changed = true; /** * Set if post thumbnails are cached * * @since 3.2.0 * @access public * @var bool */ public $thumbnails_cached = false; /** * Cached list of search stopwords. * * @since 3.7.0 * @var array */ private $stopwords; private $compat_fields = array( 'query_vars_hash', 'query_vars_changed' ); private $compat_methods = array( 'init_query_flags', 'parse_tax_query' ); /** * Resets query flags to false. * * The query flags are what page info WordPress was able to figure out. * * @since 2.0.0 * @access private */ private function init_query_flags() { $this->is_single = false; $this->is_preview = false; $this->is_page = false; $this->is_archive = false; $this->is_date = false; $this->is_year = false; $this->is_month = false; $this->is_day = false; $this->is_time = false; $this->is_author = false; $this->is_category = false; $this->is_tag = false; $this->is_tax = false; $this->is_search = false; $this->is_feed = false; $this->is_comment_feed = false; $this->is_trackback = false; $this->is_home = false; $this->is_404 = false; $this->is_paged = false; $this->is_admin = false; $this->is_attachment = false; $this->is_singular = false; $this->is_robots = false; $this->is_posts_page = false; $this->is_post_type_archive = false; } /** * Initiates object properties and sets default values. * * @since 1.5.0 * @access public */ public function init() { unset($this->posts); unset($this->query); $this->query_vars = array(); unset($this->queried_object); unset($this->queried_object_id); $this->post_count = 0; $this->current_post = -1; $this->in_the_loop = false; unset( $this->request ); unset( $this->post ); unset( $this->comments ); unset( $this->comment ); $this->comment_count = 0; $this->current_comment = -1; $this->found_posts = 0; $this->max_num_pages = 0; $this->max_num_comment_pages = 0; $this->init_query_flags(); } /** * Reparse the query vars. * * @since 1.5.0 * @access public */ public function parse_query_vars() { $this->parse_query(); } /** * Fills in the query variables, which do not exist within the parameter. * * @since 2.1.0 * @since 4.4.0 Removed the `comments_popup` public query variable. * @access public * * @param array $array Defined query variables. * @return array Complete query variables with undefined ones filled in empty. */ public function fill_query_vars($array) { $keys = array( 'error' , 'm' , 'p' , 'post_parent' , 'subpost' , 'subpost_id' , 'attachment' , 'attachment_id' , 'name' , 'static' , 'pagename' , 'page_id' , 'second' , 'minute' , 'hour' , 'day' , 'monthnum' , 'year' , 'w' , 'category_name' , 'tag' , 'cat' , 'tag_id' , 'author' , 'author_name' , 'feed' , 'tb' , 'paged' , 'meta_key' , 'meta_value' , 'preview' , 's' , 'sentence' , 'title' , 'fields' , 'menu_order' , 'embed' ); foreach ( $keys as $key ) { if ( !isset($array[$key]) ) $array[$key] = ''; } $array_keys = array( 'category__in', 'category__not_in', 'category__and', 'post__in', 'post__not_in', 'post_name__in', 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and', 'post_parent__in', 'post_parent__not_in', 'author__in', 'author__not_in' ); foreach ( $array_keys as $key ) { if ( !isset($array[$key]) ) $array[$key] = array(); } return $array; } /** * Parse a query string and set query type booleans. * * @since 1.5.0 * @since 4.2.0 Introduced the ability to order by specific clauses of a `$meta_query`, by passing the clause's * array key to `$orderby`. * @since 4.4.0 Introduced `$post_name__in` and `$title` parameters. `$s` was updated to support excluded * search terms, by prepending a hyphen. * @since 4.5.0 Removed the `$comments_popup` parameter. * Introduced the `$comment_status` and `$ping_status` parameters. * Introduced `RAND(x)` syntax for `$orderby`, which allows an integer seed value to random sorts. * @since 4.6.0 Added 'post_name__in' support for `$orderby`. Introduced the `$lazy_load_term_meta` argument. * @access public * * @param string|array $query { * Optional. Array or string of Query parameters. * * @type int $attachment_id Attachment post ID. Used for 'attachment' post_type. * @type int|string $author Author ID, or comma-separated list of IDs. * @type string $author_name User 'user_nicename'. * @type array $author__in An array of author IDs to query from. * @type array $author__not_in An array of author IDs not to query from. * @type bool $cache_results Whether to cache post information. Default true. * @type int|string $cat Category ID or comma-separated list of IDs (this or any children). * @type array $category__and An array of category IDs (AND in). * @type array $category__in An array of category IDs (OR in, no children). * @type array $category__not_in An array of category IDs (NOT in). * @type string $category_name Use category slug (not name, this or any children). * @type string $comment_status Comment status. * @type int $comments_per_page The number of comments to return per page. * Default 'comments_per_page' option. * @type array $date_query An associative array of WP_Date_Query arguments. * See WP_Date_Query::__construct(). * @type int $day Day of the month. Default empty. Accepts numbers 1-31. * @type bool $exact Whether to search by exact keyword. Default false. * @type string|array $fields Which fields to return. Single field or all fields (string), * or array of fields. 'id=>parent' uses 'id' and 'post_parent'. * Default all fields. Accepts 'ids', 'id=>parent'. * @type int $hour Hour of the day. Default empty. Accepts numbers 0-23. * @type int|bool $ignore_sticky_posts Whether to ignore sticky posts or not. Setting this to false * excludes stickies from 'post__in'. Accepts 1|true, 0|false. * Default 0|false. * @type int $m Combination YearMonth. Accepts any four-digit year and month * numbers 1-12. Default empty. * @type string $meta_compare Comparison operator to test the 'meta_value'. * @type string $meta_key Custom field key. * @type array $meta_query An associative array of WP_Meta_Query arguments. See WP_Meta_Query. * @type string $meta_value Custom field value. * @type int $meta_value_num Custom field value number. * @type int $menu_order The menu order of the posts. * @type int $monthnum The two-digit month. Default empty. Accepts numbers 1-12. * @type string $name Post slug. * @type bool $nopaging Show all posts (true) or paginate (false). Default false. * @type bool $no_found_rows Whether to skip counting the total rows found. Enabling can improve * performance. Default false. * @type int $offset The number of posts to offset before retrieval. * @type string $order Designates ascending or descending order of posts. Default 'DESC'. * Accepts 'ASC', 'DESC'. * @type string|array $orderby Sort retrieved posts by parameter. One or more options may be * passed. To use 'meta_value', or 'meta_value_num', * 'meta_key=keyname' must be also be defined. To sort by a * specific `$meta_query` clause, use that clause's array key. * Default 'date'. Accepts 'none', 'name', 'author', 'date', * 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', * 'RAND(x)' (where 'x' is an integer seed value), * 'comment_count', 'meta_value', 'meta_value_num', 'post__in', * 'post_name__in', 'post_parent__in', and the array keys * of `$meta_query`. * @type int $p Post ID. * @type int $page Show the number of posts that would show up on page X of a * static front page. * @type int $paged The number of the current page. * @type int $page_id Page ID. * @type string $pagename Page slug. * @type string $perm Show posts if user has the appropriate capability. * @type string $ping_status Ping status. * @type array $post__in An array of post IDs to retrieve, sticky posts will be included * @type string $post_mime_type The mime type of the post. Used for 'attachment' post_type. * @type array $post__not_in An array of post IDs not to retrieve. Note: a string of comma- * separated IDs will NOT work. * @type int $post_parent Page ID to retrieve child pages for. Use 0 to only retrieve * top-level pages. * @type array $post_parent__in An array containing parent page IDs to query child pages from. * @type array $post_parent__not_in An array containing parent page IDs not to query child pages from. * @type string|array $post_type A post type slug (string) or array of post type slugs. * Default 'any' if using 'tax_query'. * @type string|array $post_status A post status (string) or array of post statuses. * @type int $posts_per_page The number of posts to query for. Use -1 to request all posts. * @type int $posts_per_archive_page The number of posts to query for by archive page. Overrides * 'posts_per_page' when is_archive(), or is_search() are true. * @type array $post_name__in An array of post slugs that results must match. * @type string $s Search keyword(s). Prepending a term with a hyphen will * exclude posts matching that term. Eg, 'pillow -sofa' will * return posts containing 'pillow' but not 'sofa'. The * character used for exclusion can be modified using the * the 'wp_query_search_exclusion_prefix' filter. * @type int $second Second of the minute. Default empty. Accepts numbers 0-60. * @type bool $sentence Whether to search by phrase. Default false. * @type bool $suppress_filters Whether to suppress filters. Default false. * @type string $tag Tag slug. Comma-separated (either), Plus-separated (all). * @type array $tag__and An array of tag ids (AND in). * @type array $tag__in An array of tag ids (OR in). * @type array $tag__not_in An array of tag ids (NOT in). * @type int $tag_id Tag id or comma-separated list of IDs. * @type array $tag_slug__and An array of tag slugs (AND in). * @type array $tag_slug__in An array of tag slugs (OR in). unless 'ignore_sticky_posts' is * true. Note: a string of comma-separated IDs will NOT work. * @type array $tax_query An associative array of WP_Tax_Query arguments. * See WP_Tax_Query->queries. * @type string $title Post title. * @type bool $update_post_meta_cache Whether to update the post meta cache. Default true. * @type bool $update_post_term_cache Whether to update the post term cache. Default true. * @type bool $lazy_load_term_meta Whether to lazy-load term meta. Setting to false will * disable cache priming for term meta, so that each * get_term_meta() call will hit the database. * Defaults to the value of `$update_post_term_cache`. * @type int $w The week number of the year. Default empty. Accepts numbers 0-53. * @type int $year The four-digit year. Default empty. Accepts any four-digit year. * } */ public function parse_query( $query = '' ) { if ( ! empty( $query ) ) { $this->init(); $this->query = $this->query_vars = wp_parse_args( $query ); } elseif ( ! isset( $this->query ) ) { $this->query = $this->query_vars; } $this->query_vars = $this->fill_query_vars($this->query_vars); $qv = &$this->query_vars; $this->query_vars_changed = true; if ( ! empty($qv['robots']) ) $this->is_robots = true; if ( ! is_scalar( $qv['p'] ) || $qv['p'] < 0 ) { $qv['p'] = 0; $qv['error'] = '404'; } else { $qv['p'] = intval( $qv['p'] ); } $qv['page_id'] = absint($qv['page_id']); $qv['year'] = absint($qv['year']); $qv['monthnum'] = absint($qv['monthnum']); $qv['day'] = absint($qv['day']); $qv['w'] = absint($qv['w']); $qv['m'] = is_scalar( $qv['m'] ) ? preg_replace( '|[^0-9]|', '', $qv['m'] ) : ''; $qv['paged'] = absint($qv['paged']); $qv['cat'] = preg_replace( '|[^0-9,-]|', '', $qv['cat'] ); // comma separated list of positive or negative integers $qv['author'] = preg_replace( '|[^0-9,-]|', '', $qv['author'] ); // comma separated list of positive or negative integers $qv['pagename'] = trim( $qv['pagename'] ); $qv['name'] = trim( $qv['name'] ); $qv['title'] = trim( $qv['title'] ); if ( '' !== $qv['hour'] ) $qv['hour'] = absint($qv['hour']); if ( '' !== $qv['minute'] ) $qv['minute'] = absint($qv['minute']); if ( '' !== $qv['second'] ) $qv['second'] = absint($qv['second']); if ( '' !== $qv['menu_order'] ) $qv['menu_order'] = absint($qv['menu_order']); // Fairly insane upper bound for search string lengths. if ( ! is_scalar( $qv['s'] ) || ( ! empty( $qv['s'] ) && strlen( $qv['s'] ) > 1600 ) ) { $qv['s'] = ''; } // Compat. Map subpost to attachment. if ( '' != $qv['subpost'] ) $qv['attachment'] = $qv['subpost']; if ( '' != $qv['subpost_id'] ) $qv['attachment_id'] = $qv['subpost_id']; $qv['attachment_id'] = absint($qv['attachment_id']); if ( ('' != $qv['attachment']) || !empty($qv['attachment_id']) ) { $this->is_single = true; $this->is_attachment = true; } elseif ( '' != $qv['name'] ) { $this->is_single = true; } elseif ( $qv['p'] ) { $this->is_single = true; } elseif ( ('' !== $qv['hour']) && ('' !== $qv['minute']) &&('' !== $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) { // If year, month, day, hour, minute, and second are set, a single // post is being queried. $this->is_single = true; } elseif ( '' != $qv['static'] || '' != $qv['pagename'] || !empty($qv['page_id']) ) { $this->is_page = true; $this->is_single = false; } else { // Look for archive queries. Dates, categories, authors, search, post type archives. if ( isset( $this->query['s'] ) ) { $this->is_search = true; } if ( '' !== $qv['second'] ) { $this->is_time = true; $this->is_date = true; } if ( '' !== $qv['minute'] ) { $this->is_time = true; $this->is_date = true; } if ( '' !== $qv['hour'] ) { $this->is_time = true; $this->is_date = true; } if ( $qv['day'] ) { if ( ! $this->is_date ) { $date = sprintf( '%04d-%02d-%02d', $qv['year'], $qv['monthnum'], $qv['day'] ); if ( $qv['monthnum'] && $qv['year'] && ! wp_checkdate( $qv['monthnum'], $qv['day'], $qv['year'], $date ) ) { $qv['error'] = '404'; } else { $this->is_day = true; $this->is_date = true; } } } if ( $qv['monthnum'] ) { if ( ! $this->is_date ) { if ( 12 < $qv['monthnum'] ) { $qv['error'] = '404'; } else { $this->is_month = true; $this->is_date = true; } } } if ( $qv['year'] ) { if ( ! $this->is_date ) { $this->is_year = true; $this->is_date = true; } } if ( $qv['m'] ) { $this->is_date = true; if ( strlen($qv['m']) > 9 ) { $this->is_time = true; } elseif ( strlen( $qv['m'] ) > 7 ) { $this->is_day = true; } elseif ( strlen( $qv['m'] ) > 5 ) { $this->is_month = true; } else { $this->is_year = true; } } if ( '' != $qv['w'] ) { $this->is_date = true; } $this->query_vars_hash = false; $this->parse_tax_query( $qv ); foreach ( $this->tax_query->queries as $tax_query ) { if ( ! is_array( $tax_query ) ) { continue; } if ( isset( $tax_query['operator'] ) && 'NOT IN' != $tax_query['operator'] ) { switch ( $tax_query['taxonomy'] ) { case 'category': $this->is_category = true; break; case 'post_tag': $this->is_tag = true; break; default: $this->is_tax = true; } } } unset( $tax_query ); if ( empty($qv['author']) || ($qv['author'] == '0') ) { $this->is_author = false; } else { $this->is_author = true; } if ( '' != $qv['author_name'] ) $this->is_author = true; if ( !empty( $qv['post_type'] ) && ! is_array( $qv['post_type'] ) ) { $post_type_obj = get_post_type_object( $qv['post_type'] ); if ( ! empty( $post_type_obj->has_archive ) ) $this->is_post_type_archive = true; } if ( $this->is_post_type_archive || $this->is_date || $this->is_author || $this->is_category || $this->is_tag || $this->is_tax ) $this->is_archive = true; } if ( '' != $qv['feed'] ) $this->is_feed = true; if ( '' != $qv['embed'] ) { $this->is_embed = true; } if ( '' != $qv['tb'] ) $this->is_trackback = true; if ( '' != $qv['paged'] && ( intval($qv['paged']) > 1 ) ) $this->is_paged = true; // if we're previewing inside the write screen if ( '' != $qv['preview'] ) $this->is_preview = true; if ( is_admin() ) $this->is_admin = true; if ( false !== strpos($qv['feed'], 'comments-') ) { $qv['feed'] = str_replace('comments-', '', $qv['feed']); $qv['withcomments'] = 1; } $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment; if ( $this->is_feed && ( !empty($qv['withcomments']) || ( empty($qv['withoutcomments']) && $this->is_singular ) ) ) $this->is_comment_feed = true; if ( !( $this->is_singular || $this->is_archive || $this->is_search || $this->is_feed || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_robots ) ) $this->is_home = true; // Correct is_* for page_on_front and page_for_posts if ( $this->is_home && 'page' == get_option('show_on_front') && get_option('page_on_front') ) { $_query = wp_parse_args($this->query); // pagename can be set and empty depending on matched rewrite rules. Ignore an empty pagename. if ( isset($_query['pagename']) && '' == $_query['pagename'] ) unset($_query['pagename']); unset( $_query['embed'] ); if ( empty($_query) || !array_diff( array_keys($_query), array('preview', 'page', 'paged', 'cpage') ) ) { $this->is_page = true; $this->is_home = false; $qv['page_id'] = get_option('page_on_front'); // Correct for page_on_front if ( !empty($qv['paged']) ) { $qv['page'] = $qv['paged']; unset($qv['paged']); } } } if ( '' != $qv['pagename'] ) { $this->queried_object = get_page_by_path( $qv['pagename'] ); if ( $this->queried_object && 'attachment' == $this->queried_object->post_type ) { if ( preg_match( "/^[^%]*%(?:postname)%/", get_option( 'permalink_structure' ) ) ) { // See if we also have a post with the same slug $post = get_page_by_path( $qv['pagename'], OBJECT, 'post' ); if ( $post ) { $this->queried_object = $post; $this->is_page = false; $this->is_single = true; } } } if ( ! empty( $this->queried_object ) ) { $this->queried_object_id = (int) $this->queried_object->ID; } else { unset( $this->queried_object ); } if ( 'page' == get_option('show_on_front') && isset($this->queried_object_id) && $this->queried_object_id == get_option('page_for_posts') ) { $this->is_page = false; $this->is_home = true; $this->is_posts_page = true; } } if ( $qv['page_id'] ) { if ( 'page' == get_option('show_on_front') && $qv['page_id'] == get_option('page_for_posts') ) { $this->is_page = false; $this->is_home = true; $this->is_posts_page = true; } } if ( !empty($qv['post_type']) ) { if ( is_array($qv['post_type']) ) $qv['post_type'] = array_map('sanitize_key', $qv['post_type']); else $qv['post_type'] = sanitize_key($qv['post_type']); } if ( ! empty( $qv['post_status'] ) ) { if ( is_array( $qv['post_status'] ) ) $qv['post_status'] = array_map('sanitize_key', $qv['post_status']); else $qv['post_status'] = preg_replace('|[^a-z0-9_,-]|', '', $qv['post_status']); } if ( $this->is_posts_page && ( ! isset($qv['withcomments']) || ! $qv['withcomments'] ) ) $this->is_comment_feed = false; $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment; // Done correcting is_* for page_on_front and page_for_posts if ( '404' == $qv['error'] ) $this->set_404(); $this->is_embed = $this->is_embed && ( $this->is_singular || $this->is_404 ); $this->query_vars_hash = md5( serialize( $this->query_vars ) ); $this->query_vars_changed = false; /** * Fires after the main query vars have been parsed. * * @since 1.5.0 * * @param WP_Query &$this The WP_Query instance (passed by reference). */ do_action_ref_array( 'parse_query', array( &$this ) ); } /** * Parses various taxonomy related query vars. * * For BC, this method is not marked as protected. See [28987]. * * @access protected * @since 3.1.0 * * @param array $q The query variables. Passed by reference. */ public function parse_tax_query( &$q ) { if ( ! empty( $q['tax_query'] ) && is_array( $q['tax_query'] ) ) { $tax_query = $q['tax_query']; } else { $tax_query = array(); } if ( !empty($q['taxonomy']) && !empty($q['term']) ) { $tax_query[] = array( 'taxonomy' => $q['taxonomy'], 'terms' => array( $q['term'] ), 'field' => 'slug', ); } foreach ( get_taxonomies( array() , 'objects' ) as $taxonomy => $t ) { if ( 'post_tag' == $taxonomy ) continue; // Handled further down in the $q['tag'] block if ( $t->query_var && !empty( $q[$t->query_var] ) ) { $tax_query_defaults = array( 'taxonomy' => $taxonomy, 'field' => 'slug', ); if ( isset( $t->rewrite['hierarchical'] ) && $t->rewrite['hierarchical'] ) { $q[$t->query_var] = wp_basename( $q[$t->query_var] ); } $term = $q[$t->query_var]; if ( is_array( $term ) ) { $term = implode( ',', $term ); } if ( strpos($term, '+') !== false ) { $terms = preg_split( '/[+]+/', $term ); foreach ( $terms as $term ) { $tax_query[] = array_merge( $tax_query_defaults, array( 'terms' => array( $term ) ) ); } } else { $tax_query[] = array_merge( $tax_query_defaults, array( 'terms' => preg_split( '/[,]+/', $term ) ) ); } } } // If querystring 'cat' is an array, implode it. if ( is_array( $q['cat'] ) ) { $q['cat'] = implode( ',', $q['cat'] ); } // Category stuff if ( ! empty( $q['cat'] ) && ! $this->is_singular ) { $cat_in = $cat_not_in = array(); $cat_array = preg_split( '/[,\s]+/', urldecode( $q['cat'] ) ); $cat_array = array_map( 'intval', $cat_array ); $q['cat'] = implode( ',', $cat_array ); foreach ( $cat_array as $cat ) { if ( $cat > 0 ) $cat_in[] = $cat; elseif ( $cat < 0 ) $cat_not_in[] = abs( $cat ); } if ( ! empty( $cat_in ) ) { $tax_query[] = array( 'taxonomy' => 'category', 'terms' => $cat_in, 'field' => 'term_id', 'include_children' => true ); } if ( ! empty( $cat_not_in ) ) { $tax_query[] = array( 'taxonomy' => 'category', 'terms' => $cat_not_in, 'field' => 'term_id', 'operator' => 'NOT IN', 'include_children' => true ); } unset( $cat_array, $cat_in, $cat_not_in ); } if ( ! empty( $q['category__and'] ) && 1 === count( (array) $q['category__and'] ) ) { $q['category__and'] = (array) $q['category__and']; if ( ! isset( $q['category__in'] ) ) $q['category__in'] = array(); $q['category__in'][] = absint( reset( $q['category__and'] ) ); unset( $q['category__and'] ); } if ( ! empty( $q['category__in'] ) ) { $q['category__in'] = array_map( 'absint', array_unique( (array) $q['category__in'] ) ); $tax_query[] = array( 'taxonomy' => 'category', 'terms' => $q['category__in'], 'field' => 'term_id', 'include_children' => false ); } if ( ! empty($q['category__not_in']) ) { $q['category__not_in'] = array_map( 'absint', array_unique( (array) $q['category__not_in'] ) ); $tax_query[] = array( 'taxonomy' => 'category', 'terms' => $q['category__not_in'], 'operator' => 'NOT IN', 'include_children' => false ); } if ( ! empty($q['category__and']) ) { $q['category__and'] = array_map( 'absint', array_unique( (array) $q['category__and'] ) ); $tax_query[] = array( 'taxonomy' => 'category', 'terms' => $q['category__and'], 'field' => 'term_id', 'operator' => 'AND', 'include_children' => false ); } // If querystring 'tag' is array, implode it. if ( is_array( $q['tag'] ) ) { $q['tag'] = implode( ',', $q['tag'] ); } // Tag stuff if ( '' != $q['tag'] && !$this->is_singular && $this->query_vars_changed ) { if ( strpos($q['tag'], ',') !== false ) { $tags = preg_split('/[,\r\n\t ]+/', $q['tag']); foreach ( (array) $tags as $tag ) { $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db'); $q['tag_slug__in'][] = $tag; } } elseif ( preg_match('/[+\r\n\t ]+/', $q['tag'] ) || ! empty( $q['cat'] ) ) { $tags = preg_split('/[+\r\n\t ]+/', $q['tag']); foreach ( (array) $tags as $tag ) { $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db'); $q['tag_slug__and'][] = $tag; } } else { $q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db'); $q['tag_slug__in'][] = $q['tag']; } } if ( !empty($q['tag_id']) ) { $q['tag_id'] = absint( $q['tag_id'] ); $tax_query[] = array( 'taxonomy' => 'post_tag', 'terms' => $q['tag_id'] ); } if ( !empty($q['tag__in']) ) { $q['tag__in'] = array_map('absint', array_unique( (array) $q['tag__in'] ) ); $tax_query[] = array( 'taxonomy' => 'post_tag', 'terms' => $q['tag__in'] ); } if ( !empty($q['tag__not_in']) ) { $q['tag__not_in'] = array_map('absint', array_unique( (array) $q['tag__not_in'] ) ); $tax_query[] = array( 'taxonomy' => 'post_tag', 'terms' => $q['tag__not_in'], 'operator' => 'NOT IN' ); } if ( !empty($q['tag__and']) ) { $q['tag__and'] = array_map('absint', array_unique( (array) $q['tag__and'] ) ); $tax_query[] = array( 'taxonomy' => 'post_tag', 'terms' => $q['tag__and'], 'operator' => 'AND' ); } if ( !empty($q['tag_slug__in']) ) { $q['tag_slug__in'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__in'] ) ); $tax_query[] = array( 'taxonomy' => 'post_tag', 'terms' => $q['tag_slug__in'], 'field' => 'slug' ); } if ( !empty($q['tag_slug__and']) ) { $q['tag_slug__and'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__and'] ) ); $tax_query[] = array( 'taxonomy' => 'post_tag', 'terms' => $q['tag_slug__and'], 'field' => 'slug', 'operator' => 'AND' ); } $this->tax_query = new WP_Tax_Query( $tax_query ); /** * Fires after taxonomy-related query vars have been parsed. * * @since 3.7.0 * * @param WP_Query $this The WP_Query instance. */ do_action( 'parse_tax_query', $this ); } /** * Generate SQL for the WHERE clause based on passed search terms. * * @since 3.7.0 * * @param array $q Query variables. * @return string WHERE clause. */ protected function parse_search( &$q ) { global $wpdb; $search = ''; // added slashes screw with quote grouping when done early, so done later $q['s'] = stripslashes( $q['s'] ); if ( empty( $_GET['s'] ) && $this->is_main_query() ) $q['s'] = urldecode( $q['s'] ); // there are no line breaks in fields $q['s'] = str_replace( array( "\r", "\n" ), '', $q['s'] ); $q['search_terms_count'] = 1; if ( ! empty( $q['sentence'] ) ) { $q['search_terms'] = array( $q['s'] ); } else { if ( preg_match_all( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $q['s'], $matches ) ) { $q['search_terms_count'] = count( $matches[0] ); $q['search_terms'] = $this->parse_search_terms( $matches[0] ); // if the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence if ( empty( $q['search_terms'] ) || count( $q['search_terms'] ) > 9 ) $q['search_terms'] = array( $q['s'] ); } else { $q['search_terms'] = array( $q['s'] ); } } $n = ! empty( $q['exact'] ) ? '' : '%'; $searchand = ''; $q['search_orderby_title'] = array(); /** * Filters the prefix that indicates that a search term should be excluded from results. * * @since 4.7.0 * * @param string $exclusion_prefix The prefix. Default '-'. Returning * an empty value disables exclusions. */ $exclusion_prefix = apply_filters( 'wp_query_search_exclusion_prefix', '-' ); foreach ( $q['search_terms'] as $term ) { // If there is an $exclusion_prefix, terms prefixed with it should be excluded. $exclude = $exclusion_prefix && ( $exclusion_prefix === substr( $term, 0, 1 ) ); if ( $exclude ) { $like_op = 'NOT LIKE'; $andor_op = 'AND'; $term = substr( $term, 1 ); } else { $like_op = 'LIKE'; $andor_op = 'OR'; } if ( $n && ! $exclude ) { $like = '%' . $wpdb->esc_like( $term ) . '%'; $q['search_orderby_title'][] = $wpdb->prepare( "{$wpdb->posts}.post_title LIKE %s", $like ); } $like = $n . $wpdb->esc_like( $term ) . $n; $search .= $wpdb->prepare( "{$searchand}(({$wpdb->posts}.post_title $like_op %s) $andor_op ({$wpdb->posts}.post_excerpt $like_op %s) $andor_op ({$wpdb->posts}.post_content $like_op %s))", $like, $like, $like ); $searchand = ' AND '; } if ( ! empty( $search ) ) { $search = " AND ({$search}) "; if ( ! is_user_logged_in() ) { $search .= " AND ({$wpdb->posts}.post_password = '') "; } } return $search; } /** * Check if the terms are suitable for searching. * * Uses an array of stopwords (terms) that are excluded from the separate * term matching when searching for posts. The list of English stopwords is * the approximate search engines list, and is translatable. * * @since 3.7.0 * * @param array $terms Terms to check. * @return array Terms that are not stopwords. */ protected function parse_search_terms( $terms ) { $strtolower = function_exists( 'mb_strtolower' ) ? 'mb_strtolower' : 'strtolower'; $checked = array(); $stopwords = $this->get_search_stopwords(); foreach ( $terms as $term ) { // keep before/after spaces when term is for exact match if ( preg_match( '/^".+"$/', $term ) ) $term = trim( $term, "\"'" ); else $term = trim( $term, "\"' " ); // Avoid single A-Z and single dashes. if ( ! $term || ( 1 === strlen( $term ) && preg_match( '/^[a-z\-]$/i', $term ) ) ) continue; if ( in_array( call_user_func( $strtolower, $term ), $stopwords, true ) ) continue; $checked[] = $term; } return $checked; } /** * Retrieve stopwords used when parsing search terms. * * @since 3.7.0 * * @return array Stopwords. */ protected function get_search_stopwords() { if ( isset( $this->stopwords ) ) return $this->stopwords; /* translators: This is a comma-separated list of very common words that should be excluded from a search, * like a, an, and the. These are usually called "stopwords". You should not simply translate these individual * words into your language. Instead, look for and provide commonly accepted stopwords in your language. */ $words = explode( ',', _x( 'about,an,are,as,at,be,by,com,for,from,how,in,is,it,of,on,or,that,the,this,to,was,what,when,where,who,will,with,www', 'Comma-separated list of search stopwords in your language' ) ); $stopwords = array(); foreach ( $words as $word ) { $word = trim( $word, "\r\n\t " ); if ( $word ) $stopwords[] = $word; } /** * Filters stopwords used when parsing search terms. * * @since 3.7.0 * * @param array $stopwords Stopwords. */ $this->stopwords = apply_filters( 'wp_search_stopwords', $stopwords ); return $this->stopwords; } /** * Generate SQL for the ORDER BY condition based on passed search terms. * * @param array $q Query variables. * @return string ORDER BY clause. */ protected function parse_search_order( &$q ) { global $wpdb; if ( $q['search_terms_count'] > 1 ) { $num_terms = count( $q['search_orderby_title'] ); // If the search terms contain negative queries, don't bother ordering by sentence matches. $like = ''; if ( ! preg_match( '/(?:\s|^)\-/', $q['s'] ) ) { $like = '%' . $wpdb->esc_like( $q['s'] ) . '%'; } $search_orderby = ''; // sentence match in 'post_title' if ( $like ) { $search_orderby .= $wpdb->prepare( "WHEN {$wpdb->posts}.post_title LIKE %s THEN 1 ", $like ); } // sanity limit, sort as sentence when more than 6 terms // (few searches are longer than 6 terms and most titles are not) if ( $num_terms < 7 ) { // all words in title $search_orderby .= 'WHEN ' . implode( ' AND ', $q['search_orderby_title'] ) . ' THEN 2 '; // any word in title, not needed when $num_terms == 1 if ( $num_terms > 1 ) $search_orderby .= 'WHEN ' . implode( ' OR ', $q['search_orderby_title'] ) . ' THEN 3 '; } // Sentence match in 'post_content' and 'post_excerpt'. if ( $like ) { $search_orderby .= $wpdb->prepare( "WHEN {$wpdb->posts}.post_excerpt LIKE %s THEN 4 ", $like ); $search_orderby .= $wpdb->prepare( "WHEN {$wpdb->posts}.post_content LIKE %s THEN 5 ", $like ); } if ( $search_orderby ) { $search_orderby = '(CASE ' . $search_orderby . 'ELSE 6 END)'; } } else { // single word or sentence search $search_orderby = reset( $q['search_orderby_title'] ) . ' DESC'; } return $search_orderby; } /** * If the passed orderby value is allowed, convert the alias to a * properly-prefixed orderby value. * * @since 4.0.0 * @access protected * * @param string $orderby Alias for the field to order by. * @return string|false Table-prefixed value to used in the ORDER clause. False otherwise. */ protected function parse_orderby( $orderby ) { global $wpdb; // Used to filter values. $allowed_keys = array( 'post_name', 'post_author', 'post_date', 'post_title', 'post_modified', 'post_parent', 'post_type', 'name', 'author', 'date', 'title', 'modified', 'parent', 'type', 'ID', 'menu_order', 'comment_count', 'rand', ); $primary_meta_key = ''; $primary_meta_query = false; $meta_clauses = $this->meta_query->get_clauses(); if ( ! empty( $meta_clauses ) ) { $primary_meta_query = reset( $meta_clauses ); if ( ! empty( $primary_meta_query['key'] ) ) { $primary_meta_key = $primary_meta_query['key']; $allowed_keys[] = $primary_meta_key; } $allowed_keys[] = 'meta_value'; $allowed_keys[] = 'meta_value_num'; $allowed_keys = array_merge( $allowed_keys, array_keys( $meta_clauses ) ); } // If RAND() contains a seed value, sanitize and add to allowed keys. $rand_with_seed = false; if ( preg_match( '/RAND\(([0-9]+)\)/i', $orderby, $matches ) ) { $orderby = sprintf( 'RAND(%s)', intval( $matches[1] ) ); $allowed_keys[] = $orderby; $rand_with_seed = true; } if ( ! in_array( $orderby, $allowed_keys, true ) ) { return false; } switch ( $orderby ) { case 'post_name': case 'post_author': case 'post_date': case 'post_title': case 'post_modified': case 'post_parent': case 'post_type': case 'ID': case 'menu_order': case 'comment_count': $orderby_clause = "{$wpdb->posts}.{$orderby}"; break; case 'rand': $orderby_clause = 'RAND()'; break; case $primary_meta_key: case 'meta_value': if ( ! empty( $primary_meta_query['type'] ) ) { $orderby_clause = "CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})"; } else { $orderby_clause = "{$primary_meta_query['alias']}.meta_value"; } break; case 'meta_value_num': $orderby_clause = "{$primary_meta_query['alias']}.meta_value+0"; break; default: if ( array_key_exists( $orderby, $meta_clauses ) ) { // $orderby corresponds to a meta_query clause. $meta_clause = $meta_clauses[ $orderby ]; $orderby_clause = "CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})"; } elseif ( $rand_with_seed ) { $orderby_clause = $orderby; } else { // Default: order by post field. $orderby_clause = "{$wpdb->posts}.post_" . sanitize_key( $orderby ); } break; } return $orderby_clause; } /** * Parse an 'order' query variable and cast it to ASC or DESC as necessary. * * @since 4.0.0 * @access protected * * @param string $order The 'order' query variable. * @return string The sanitized 'order' query variable. */ protected function parse_order( $order ) { if ( ! is_string( $order ) || empty( $order ) ) { return 'DESC'; } if ( 'ASC' === strtoupper( $order ) ) { return 'ASC'; } else { return 'DESC'; } } /** * Sets the 404 property and saves whether query is feed. * * @since 2.0.0 * @access public */ public function set_404() { $is_feed = $this->is_feed; $this->init_query_flags(); $this->is_404 = true; $this->is_feed = $is_feed; } /** * Retrieve query variable. * * @since 1.5.0 * @since 3.9.0 The `$default` argument was introduced. * * @access public * * @param string $query_var Query variable key. * @param mixed $default Optional. Value to return if the query variable is not set. Default empty. * @return mixed Contents of the query variable. */ public function get( $query_var, $default = '' ) { if ( isset( $this->query_vars[ $query_var ] ) ) { return $this->query_vars[ $query_var ]; } return $default; } /** * Set query variable. * * @since 1.5.0 * @access public * * @param string $query_var Query variable key. * @param mixed $value Query variable value. */ public function set($query_var, $value) { $this->query_vars[$query_var] = $value; } /** * Retrieve the posts based on query variables. * * There are a few filters and actions that can be used to modify the post * database query. * * @since 1.5.0 * @access public * * @return array List of posts. */ public function get_posts() { global $wpdb; $this->parse_query(); /** * Fires after the query variable object is created, but before the actual query is run. * * Note: If using conditional tags, use the method versions within the passed instance * (e.g. $this->is_main_query() instead of is_main_query()). This is because the functions * like is_main_query() test against the global $wp_query instance, not the passed one. * * @since 2.0.0 * * @param WP_Query &$this The WP_Query instance (passed by reference). */ do_action_ref_array( 'pre_get_posts', array( &$this ) ); // Shorthand. $q = &$this->query_vars; // Fill again in case pre_get_posts unset some vars. $q = $this->fill_query_vars($q); // Parse meta query $this->meta_query = new WP_Meta_Query(); $this->meta_query->parse_query_vars( $q ); // Set a flag if a pre_get_posts hook changed the query vars. $hash = md5( serialize( $this->query_vars ) ); if ( $hash != $this->query_vars_hash ) { $this->query_vars_changed = true; $this->query_vars_hash = $hash; } unset($hash); // First let's clear some variables $distinct = ''; $whichauthor = ''; $whichmimetype = ''; $where = ''; $limits = ''; $join = ''; $search = ''; $groupby = ''; $post_status_join = false; $page = 1; if ( isset( $q['caller_get_posts'] ) ) { _deprecated_argument( 'WP_Query', '3.1.0', __( '"caller_get_posts" is deprecated. Use "ignore_sticky_posts" instead.' ) ); if ( !isset( $q['ignore_sticky_posts'] ) ) $q['ignore_sticky_posts'] = $q['caller_get_posts']; } if ( !isset( $q['ignore_sticky_posts'] ) ) $q['ignore_sticky_posts'] = false; if ( !isset($q['suppress_filters']) ) $q['suppress_filters'] = false; if ( !isset($q['cache_results']) ) { if ( wp_using_ext_object_cache() ) $q['cache_results'] = false; else $q['cache_results'] = true; } if ( !isset($q['update_post_term_cache']) ) $q['update_post_term_cache'] = true; if ( ! isset( $q['lazy_load_term_meta'] ) ) { $q['lazy_load_term_meta'] = $q['update_post_term_cache']; } if ( !isset($q['update_post_meta_cache']) ) $q['update_post_meta_cache'] = true; if ( !isset($q['post_type']) ) { if ( $this->is_search ) $q['post_type'] = 'any'; else $q['post_type'] = ''; } $post_type = $q['post_type']; if ( empty( $q['posts_per_page'] ) ) { $q['posts_per_page'] = get_option( 'posts_per_page' ); } if ( isset($q['showposts']) && $q['showposts'] ) { $q['showposts'] = (int) $q['showposts']; $q['posts_per_page'] = $q['showposts']; } if ( (isset($q['posts_per_archive_page']) && $q['posts_per_archive_page'] != 0) && ($this->is_archive || $this->is_search) ) $q['posts_per_page'] = $q['posts_per_archive_page']; if ( !isset($q['nopaging']) ) { if ( $q['posts_per_page'] == -1 ) { $q['nopaging'] = true; } else { $q['nopaging'] = false; } } if ( $this->is_feed ) { // This overrides posts_per_page. if ( ! empty( $q['posts_per_rss'] ) ) { $q['posts_per_page'] = $q['posts_per_rss']; } else { $q['posts_per_page'] = get_option( 'posts_per_rss' ); } $q['nopaging'] = false; } $q['posts_per_page'] = (int) $q['posts_per_page']; if ( $q['posts_per_page'] < -1 ) $q['posts_per_page'] = abs($q['posts_per_page']); elseif ( $q['posts_per_page'] == 0 ) $q['posts_per_page'] = 1; if ( !isset($q['comments_per_page']) || $q['comments_per_page'] == 0 ) $q['comments_per_page'] = get_option('comments_per_page'); if ( $this->is_home && (empty($this->query) || $q['preview'] == 'true') && ( 'page' == get_option('show_on_front') ) && get_option('page_on_front') ) { $this->is_page = true; $this->is_home = false; $q['page_id'] = get_option('page_on_front'); } if ( isset($q['page']) ) { $q['page'] = trim($q['page'], '/'); $q['page'] = absint($q['page']); } // If true, forcibly turns off SQL_CALC_FOUND_ROWS even when limits are present. if ( isset($q['no_found_rows']) ) $q['no_found_rows'] = (bool) $q['no_found_rows']; else $q['no_found_rows'] = false; switch ( $q['fields'] ) { case 'ids': $fields = "{$wpdb->posts}.ID"; break; case 'id=>parent': $fields = "{$wpdb->posts}.ID, {$wpdb->posts}.post_parent"; break; default: $fields = "{$wpdb->posts}.*"; } if ( '' !== $q['menu_order'] ) { $where .= " AND {$wpdb->posts}.menu_order = " . $q['menu_order']; } // The "m" parameter is meant for months but accepts datetimes of varying specificity if ( $q['m'] ) { $where .= " AND YEAR({$wpdb->posts}.post_date)=" . substr($q['m'], 0, 4); if ( strlen($q['m']) > 5 ) { $where .= " AND MONTH({$wpdb->posts}.post_date)=" . substr($q['m'], 4, 2); } if ( strlen($q['m']) > 7 ) { $where .= " AND DAYOFMONTH({$wpdb->posts}.post_date)=" . substr($q['m'], 6, 2); } if ( strlen($q['m']) > 9 ) { $where .= " AND HOUR({$wpdb->posts}.post_date)=" . substr($q['m'], 8, 2); } if ( strlen($q['m']) > 11 ) { $where .= " AND MINUTE({$wpdb->posts}.post_date)=" . substr($q['m'], 10, 2); } if ( strlen($q['m']) > 13 ) { $where .= " AND SECOND({$wpdb->posts}.post_date)=" . substr($q['m'], 12, 2); } } // Handle the other individual date parameters $date_parameters = array(); if ( '' !== $q['hour'] ) $date_parameters['hour'] = $q['hour']; if ( '' !== $q['minute'] ) $date_parameters['minute'] = $q['minute']; if ( '' !== $q['second'] ) $date_parameters['second'] = $q['second']; if ( $q['year'] ) $date_parameters['year'] = $q['year']; if ( $q['monthnum'] ) $date_parameters['monthnum'] = $q['monthnum']; if ( $q['w'] ) $date_parameters['week'] = $q['w']; if ( $q['day'] ) $date_parameters['day'] = $q['day']; if ( $date_parameters ) { $date_query = new WP_Date_Query( array( $date_parameters ) ); $where .= $date_query->get_sql(); } unset( $date_parameters, $date_query ); // Handle complex date queries if ( ! empty( $q['date_query'] ) ) { $this->date_query = new WP_Date_Query( $q['date_query'] ); $where .= $this->date_query->get_sql(); } // If we've got a post_type AND it's not "any" post_type. if ( !empty($q['post_type']) && 'any' != $q['post_type'] ) { foreach ( (array)$q['post_type'] as $_post_type ) { $ptype_obj = get_post_type_object($_post_type); if ( !$ptype_obj || !$ptype_obj->query_var || empty($q[ $ptype_obj->query_var ]) ) continue; if ( ! $ptype_obj->hierarchical ) { // Non-hierarchical post types can directly use 'name'. $q['name'] = $q[ $ptype_obj->query_var ]; } else { // Hierarchical post types will operate through 'pagename'. $q['pagename'] = $q[ $ptype_obj->query_var ]; $q['name'] = ''; } // Only one request for a slug is possible, this is why name & pagename are overwritten above. break; } //end foreach unset($ptype_obj); } if ( '' !== $q['title'] ) { $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_title = %s", stripslashes( $q['title'] ) ); } // Parameters related to 'post_name'. if ( '' != $q['name'] ) { $q['name'] = sanitize_title_for_query( $q['name'] ); $where .= " AND {$wpdb->posts}.post_name = '" . $q['name'] . "'"; } elseif ( '' != $q['pagename'] ) { if ( isset($this->queried_object_id) ) { $reqpage = $this->queried_object_id; } else { if ( 'page' != $q['post_type'] ) { foreach ( (array)$q['post_type'] as $_post_type ) { $ptype_obj = get_post_type_object($_post_type); if ( !$ptype_obj || !$ptype_obj->hierarchical ) continue; $reqpage = get_page_by_path($q['pagename'], OBJECT, $_post_type); if ( $reqpage ) break; } unset($ptype_obj); } else { $reqpage = get_page_by_path($q['pagename']); } if ( !empty($reqpage) ) $reqpage = $reqpage->ID; else $reqpage = 0; } $page_for_posts = get_option('page_for_posts'); if ( ('page' != get_option('show_on_front') ) || empty($page_for_posts) || ( $reqpage != $page_for_posts ) ) { $q['pagename'] = sanitize_title_for_query( wp_basename( $q['pagename'] ) ); $q['name'] = $q['pagename']; $where .= " AND ({$wpdb->posts}.ID = '$reqpage')"; $reqpage_obj = get_post( $reqpage ); if ( is_object($reqpage_obj) && 'attachment' == $reqpage_obj->post_type ) { $this->is_attachment = true; $post_type = $q['post_type'] = 'attachment'; $this->is_page = true; $q['attachment_id'] = $reqpage; } } } elseif ( '' != $q['attachment'] ) { $q['attachment'] = sanitize_title_for_query( wp_basename( $q['attachment'] ) ); $q['name'] = $q['attachment']; $where .= " AND {$wpdb->posts}.post_name = '" . $q['attachment'] . "'"; } elseif ( is_array( $q['post_name__in'] ) && ! empty( $q['post_name__in'] ) ) { $q['post_name__in'] = array_map( 'sanitize_title_for_query', $q['post_name__in'] ); $post_name__in = "'" . implode( "','", $q['post_name__in'] ) . "'"; $where .= " AND {$wpdb->posts}.post_name IN ($post_name__in)"; } // If an attachment is requested by number, let it supersede any post number. if ( $q['attachment_id'] ) $q['p'] = absint($q['attachment_id']); // If a post number is specified, load that post if ( $q['p'] ) { $where .= " AND {$wpdb->posts}.ID = " . $q['p']; } elseif ( $q['post__in'] ) { $post__in = implode(',', array_map( 'absint', $q['post__in'] )); $where .= " AND {$wpdb->posts}.ID IN ($post__in)"; } elseif ( $q['post__not_in'] ) { $post__not_in = implode(',', array_map( 'absint', $q['post__not_in'] )); $where .= " AND {$wpdb->posts}.ID NOT IN ($post__not_in)"; } if ( is_numeric( $q['post_parent'] ) ) { $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_parent = %d ", $q['post_parent'] ); } elseif ( $q['post_parent__in'] ) { $post_parent__in = implode( ',', array_map( 'absint', $q['post_parent__in'] ) ); $where .= " AND {$wpdb->posts}.post_parent IN ($post_parent__in)"; } elseif ( $q['post_parent__not_in'] ) { $post_parent__not_in = implode( ',', array_map( 'absint', $q['post_parent__not_in'] ) ); $where .= " AND {$wpdb->posts}.post_parent NOT IN ($post_parent__not_in)"; } if ( $q['page_id'] ) { if ( ('page' != get_option('show_on_front') ) || ( $q['page_id'] != get_option('page_for_posts') ) ) { $q['p'] = $q['page_id']; $where = " AND {$wpdb->posts}.ID = " . $q['page_id']; } } // If a search pattern is specified, load the posts that match. if ( strlen( $q['s'] ) ) { $search = $this->parse_search( $q ); } if ( ! $q['suppress_filters'] ) { /** * Filters the search SQL that is used in the WHERE clause of WP_Query. * * @since 3.0.0 * * @param string $search Search SQL for WHERE clause. * @param WP_Query $this The current WP_Query object. */ $search = apply_filters_ref_array( 'posts_search', array( $search, &$this ) ); } // Taxonomies if ( !$this->is_singular ) { $this->parse_tax_query( $q ); $clauses = $this->tax_query->get_sql( $wpdb->posts, 'ID' ); $join .= $clauses['join']; $where .= $clauses['where']; } if ( $this->is_tax ) { if ( empty($post_type) ) { // Do a fully inclusive search for currently registered post types of queried taxonomies $post_type = array(); $taxonomies = array_keys( $this->tax_query->queried_terms ); foreach ( get_post_types( array( 'exclude_from_search' => false ) ) as $pt ) { $object_taxonomies = $pt === 'attachment' ? get_taxonomies_for_attachments() : get_object_taxonomies( $pt ); if ( array_intersect( $taxonomies, $object_taxonomies ) ) $post_type[] = $pt; } if ( ! $post_type ) $post_type = 'any'; elseif ( count( $post_type ) == 1 ) $post_type = $post_type[0]; $post_status_join = true; } elseif ( in_array('attachment', (array) $post_type) ) { $post_status_join = true; } } /* * Ensure that 'taxonomy', 'term', 'term_id', 'cat', and * 'category_name' vars are set for backward compatibility. */ if ( ! empty( $this->tax_query->queried_terms ) ) { /* * Set 'taxonomy', 'term', and 'term_id' to the * first taxonomy other than 'post_tag' or 'category'. */ if ( ! isset( $q['taxonomy'] ) ) { foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) { if ( empty( $queried_items['terms'][0] ) ) { continue; } if ( ! in_array( $queried_taxonomy, array( 'category', 'post_tag' ) ) ) { $q['taxonomy'] = $queried_taxonomy; if ( 'slug' === $queried_items['field'] ) { $q['term'] = $queried_items['terms'][0]; } else { $q['term_id'] = $queried_items['terms'][0]; } // Take the first one we find. break; } } } // 'cat', 'category_name', 'tag_id' foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) { if ( empty( $queried_items['terms'][0] ) ) { continue; } if ( 'category' === $queried_taxonomy ) { $the_cat = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'category' ); if ( $the_cat ) { $this->set( 'cat', $the_cat->term_id ); $this->set( 'category_name', $the_cat->slug ); } unset( $the_cat ); } if ( 'post_tag' === $queried_taxonomy ) { $the_tag = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'post_tag' ); if ( $the_tag ) { $this->set( 'tag_id', $the_tag->term_id ); } unset( $the_tag ); } } } if ( !empty( $this->tax_query->queries ) || !empty( $this->meta_query->queries ) ) { $groupby = "{$wpdb->posts}.ID"; } // Author/user stuff if ( ! empty( $q['author'] ) && $q['author'] != '0' ) { $q['author'] = addslashes_gpc( '' . urldecode( $q['author'] ) ); $authors = array_unique( array_map( 'intval', preg_split( '/[,\s]+/', $q['author'] ) ) ); foreach ( $authors as $author ) { $key = $author > 0 ? 'author__in' : 'author__not_in'; $q[$key][] = abs( $author ); } $q['author'] = implode( ',', $authors ); } if ( ! empty( $q['author__not_in'] ) ) { $author__not_in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__not_in'] ) ) ); $where .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) "; } elseif ( ! empty( $q['author__in'] ) ) { $author__in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__in'] ) ) ); $where .= " AND {$wpdb->posts}.post_author IN ($author__in) "; } // Author stuff for nice URLs if ( '' != $q['author_name'] ) { if ( strpos($q['author_name'], '/') !== false ) { $q['author_name'] = explode('/', $q['author_name']); if ( $q['author_name'][ count($q['author_name'])-1 ] ) { $q['author_name'] = $q['author_name'][count($q['author_name'])-1]; // no trailing slash } else { $q['author_name'] = $q['author_name'][count($q['author_name'])-2]; // there was a trailing slash } } $q['author_name'] = sanitize_title_for_query( $q['author_name'] ); $q['author'] = get_user_by('slug', $q['author_name']); if ( $q['author'] ) $q['author'] = $q['author']->ID; $whichauthor .= " AND ({$wpdb->posts}.post_author = " . absint($q['author']) . ')'; } // MIME-Type stuff for attachment browsing if ( isset( $q['post_mime_type'] ) && '' != $q['post_mime_type'] ) { $whichmimetype = wp_post_mime_type_where( $q['post_mime_type'], $wpdb->posts ); } $where .= $search . $whichauthor . $whichmimetype; if ( ! empty( $this->meta_query->queries ) ) { $clauses = $this->meta_query->get_sql( 'post', $wpdb->posts, 'ID', $this ); $join .= $clauses['join']; $where .= $clauses['where']; } $rand = ( isset( $q['orderby'] ) && 'rand' === $q['orderby'] ); if ( ! isset( $q['order'] ) ) { $q['order'] = $rand ? '' : 'DESC'; } else { $q['order'] = $rand ? '' : $this->parse_order( $q['order'] ); } // Order by. if ( empty( $q['orderby'] ) ) { /* * Boolean false or empty array blanks out ORDER BY, * while leaving the value unset or otherwise empty sets the default. */ if ( isset( $q['orderby'] ) && ( is_array( $q['orderby'] ) || false === $q['orderby'] ) ) { $orderby = ''; } else { $orderby = "{$wpdb->posts}.post_date " . $q['order']; } } elseif ( 'none' == $q['orderby'] ) { $orderby = ''; } elseif ( $q['orderby'] == 'post__in' && ! empty( $post__in ) ) { $orderby = "FIELD( {$wpdb->posts}.ID, $post__in )"; } elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) { $orderby = "FIELD( {$wpdb->posts}.post_parent, $post_parent__in )"; } elseif ( $q['orderby'] == 'post_name__in' && ! empty( $post_name__in ) ) { $orderby = "FIELD( {$wpdb->posts}.post_name, $post_name__in )"; } else { $orderby_array = array(); if ( is_array( $q['orderby'] ) ) { foreach ( $q['orderby'] as $_orderby => $order ) { $orderby = addslashes_gpc( urldecode( $_orderby ) ); $parsed = $this->parse_orderby( $orderby ); if ( ! $parsed ) { continue; } $orderby_array[] = $parsed . ' ' . $this->parse_order( $order ); } $orderby = implode( ', ', $orderby_array ); } else { $q['orderby'] = urldecode( $q['orderby'] ); $q['orderby'] = addslashes_gpc( $q['orderby'] ); foreach ( explode( ' ', $q['orderby'] ) as $i => $orderby ) { $parsed = $this->parse_orderby( $orderby ); // Only allow certain values for safety. if ( ! $parsed ) { continue; } $orderby_array[] = $parsed; } $orderby = implode( ' ' . $q['order'] . ', ', $orderby_array ); if ( empty( $orderby ) ) { $orderby = "{$wpdb->posts}.post_date " . $q['order']; } elseif ( ! empty( $q['order'] ) ) { $orderby .= " {$q['order']}"; } } } // Order search results by relevance only when another "orderby" is not specified in the query. if ( ! empty( $q['s'] ) ) { $search_orderby = ''; if ( ! empty( $q['search_orderby_title'] ) && ( empty( $q['orderby'] ) && ! $this->is_feed ) || ( isset( $q['orderby'] ) && 'relevance' === $q['orderby'] ) ) $search_orderby = $this->parse_search_order( $q ); if ( ! $q['suppress_filters'] ) { /** * Filters the ORDER BY used when ordering search results. * * @since 3.7.0 * * @param string $search_orderby The ORDER BY clause. * @param WP_Query $this The current WP_Query instance. */ $search_orderby = apply_filters( 'posts_search_orderby', $search_orderby, $this ); } if ( $search_orderby ) $orderby = $orderby ? $search_orderby . ', ' . $orderby : $search_orderby; } if ( is_array( $post_type ) && count( $post_type ) > 1 ) { $post_type_cap = 'multiple_post_type'; } else { if ( is_array( $post_type ) ) $post_type = reset( $post_type ); $post_type_object = get_post_type_object( $post_type ); if ( empty( $post_type_object ) ) $post_type_cap = $post_type; } if ( isset( $q['post_password'] ) ) { $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_password = %s", $q['post_password'] ); if ( empty( $q['perm'] ) ) { $q['perm'] = 'readable'; } } elseif ( isset( $q['has_password'] ) ) { $where .= sprintf( " AND {$wpdb->posts}.post_password %s ''", $q['has_password'] ? '!=' : '=' ); } if ( ! empty( $q['comment_status'] ) ) { $where .= $wpdb->prepare( " AND {$wpdb->posts}.comment_status = %s ", $q['comment_status'] ); } if ( ! empty( $q['ping_status'] ) ) { $where .= $wpdb->prepare( " AND {$wpdb->posts}.ping_status = %s ", $q['ping_status'] ); } if ( 'any' == $post_type ) { $in_search_post_types = get_post_types( array('exclude_from_search' => false) ); if ( empty( $in_search_post_types ) ) { $where .= ' AND 1=0 '; } else { $where .= " AND {$wpdb->posts}.post_type IN ('" . join( "', '", array_map( 'esc_sql', $in_search_post_types ) ) . "')"; } } elseif ( !empty( $post_type ) && is_array( $post_type ) ) { $where .= " AND {$wpdb->posts}.post_type IN ('" . join("', '", esc_sql( $post_type ) ) . "')"; } elseif ( ! empty( $post_type ) ) { $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_type = %s", $post_type ); $post_type_object = get_post_type_object ( $post_type ); } elseif ( $this->is_attachment ) { $where .= " AND {$wpdb->posts}.post_type = 'attachment'"; $post_type_object = get_post_type_object ( 'attachment' ); } elseif ( $this->is_page ) { $where .= " AND {$wpdb->posts}.post_type = 'page'"; $post_type_object = get_post_type_object ( 'page' ); } else { $where .= " AND {$wpdb->posts}.post_type = 'post'"; $post_type_object = get_post_type_object ( 'post' ); } $edit_cap = 'edit_post'; $read_cap = 'read_post'; if ( ! empty( $post_type_object ) ) { $edit_others_cap = $post_type_object->cap->edit_others_posts; $read_private_cap = $post_type_object->cap->read_private_posts; } else { $edit_others_cap = 'edit_others_' . $post_type_cap . 's'; $read_private_cap = 'read_private_' . $post_type_cap . 's'; } $user_id = get_current_user_id(); $q_status = array(); if ( ! empty( $q['post_status'] ) ) { $statuswheres = array(); $q_status = $q['post_status']; if ( ! is_array( $q_status ) ) $q_status = explode(',', $q_status); $r_status = array(); $p_status = array(); $e_status = array(); if ( in_array( 'any', $q_status ) ) { foreach ( get_post_stati( array( 'exclude_from_search' => true ) ) as $status ) { if ( ! in_array( $status, $q_status ) ) { $e_status[] = "{$wpdb->posts}.post_status <> '$status'"; } } } else { foreach ( get_post_stati() as $status ) { if ( in_array( $status, $q_status ) ) { if ( 'private' == $status ) { $p_status[] = "{$wpdb->posts}.post_status = '$status'"; } else { $r_status[] = "{$wpdb->posts}.post_status = '$status'"; } } } } if ( empty($q['perm'] ) || 'readable' != $q['perm'] ) { $r_status = array_merge($r_status, $p_status); unset($p_status); } if ( !empty($e_status) ) { $statuswheres[] = "(" . join( ' AND ', $e_status ) . ")"; } if ( !empty($r_status) ) { if ( !empty($q['perm'] ) && 'editable' == $q['perm'] && !current_user_can($edit_others_cap) ) { $statuswheres[] = "({$wpdb->posts}.post_author = $user_id " . "AND (" . join( ' OR ', $r_status ) . "))"; } else { $statuswheres[] = "(" . join( ' OR ', $r_status ) . ")"; } } if ( !empty($p_status) ) { if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can($read_private_cap) ) { $statuswheres[] = "({$wpdb->posts}.post_author = $user_id " . "AND (" . join( ' OR ', $p_status ) . "))"; } else { $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")"; } } if ( $post_status_join ) { $join .= " LEFT JOIN {$wpdb->posts} AS p2 ON ({$wpdb->posts}.post_parent = p2.ID) "; foreach ( $statuswheres as $index => $statuswhere ) { $statuswheres[$index] = "($statuswhere OR ({$wpdb->posts}.post_status = 'inherit' AND " . str_replace( $wpdb->posts, 'p2', $statuswhere ) . "))"; } } $where_status = implode( ' OR ', $statuswheres ); if ( ! empty( $where_status ) ) { $where .= " AND ($where_status)"; } } elseif ( !$this->is_singular ) { $where .= " AND ({$wpdb->posts}.post_status = 'publish'"; // Add public states. $public_states = get_post_stati( array('public' => true) ); foreach ( (array) $public_states as $state ) { if ( 'publish' == $state ) // Publish is hard-coded above. continue; $where .= " OR {$wpdb->posts}.post_status = '$state'"; } if ( $this->is_admin ) { // Add protected states that should show in the admin all list. $admin_all_states = get_post_stati( array('protected' => true, 'show_in_admin_all_list' => true) ); foreach ( (array) $admin_all_states as $state ) { $where .= " OR {$wpdb->posts}.post_status = '$state'"; } } if ( is_user_logged_in() ) { // Add private states that are limited to viewing by the author of a post or someone who has caps to read private states. $private_states = get_post_stati( array('private' => true) ); foreach ( (array) $private_states as $state ) { $where .= current_user_can( $read_private_cap ) ? " OR {$wpdb->posts}.post_status = '$state'" : " OR {$wpdb->posts}.post_author = $user_id AND {$wpdb->posts}.post_status = '$state'"; } } $where .= ')'; } /* * Apply filters on where and join prior to paging so that any * manipulations to them are reflected in the paging by day queries. */ if ( !$q['suppress_filters'] ) { /** * Filters the WHERE clause of the query. * * @since 1.5.0 * * @param string $where The WHERE clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $where = apply_filters_ref_array( 'posts_where', array( $where, &$this ) ); /** * Filters the JOIN clause of the query. * * @since 1.5.0 * * @param string $where The JOIN clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $join = apply_filters_ref_array( 'posts_join', array( $join, &$this ) ); } // Paging if ( empty($q['nopaging']) && !$this->is_singular ) { $page = absint($q['paged']); if ( !$page ) $page = 1; // If 'offset' is provided, it takes precedence over 'paged'. if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) ) { $q['offset'] = absint( $q['offset'] ); $pgstrt = $q['offset'] . ', '; } else { $pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', '; } $limits = 'LIMIT ' . $pgstrt . $q['posts_per_page']; } // Comments feeds if ( $this->is_comment_feed && ! $this->is_singular ) { if ( $this->is_archive || $this->is_search ) { $cjoin = "JOIN {$wpdb->posts} ON ({$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID) $join "; $cwhere = "WHERE comment_approved = '1' $where"; $cgroupby = "{$wpdb->comments}.comment_id"; } else { // Other non singular e.g. front $cjoin = "JOIN {$wpdb->posts} ON ( {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID )"; $cwhere = "WHERE ( post_status = 'publish' OR ( post_status = 'inherit' AND post_type = 'attachment' ) ) AND comment_approved = '1'"; $cgroupby = ''; } if ( !$q['suppress_filters'] ) { /** * Filters the JOIN clause of the comments feed query before sending. * * @since 2.2.0 * * @param string $cjoin The JOIN clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $cjoin = apply_filters_ref_array( 'comment_feed_join', array( $cjoin, &$this ) ); /** * Filters the WHERE clause of the comments feed query before sending. * * @since 2.2.0 * * @param string $cwhere The WHERE clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $cwhere = apply_filters_ref_array( 'comment_feed_where', array( $cwhere, &$this ) ); /** * Filters the GROUP BY clause of the comments feed query before sending. * * @since 2.2.0 * * @param string $cgroupby The GROUP BY clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( $cgroupby, &$this ) ); /** * Filters the ORDER BY clause of the comments feed query before sending. * * @since 2.8.0 * * @param string $corderby The ORDER BY clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) ); /** * Filters the LIMIT clause of the comments feed query before sending. * * @since 2.8.0 * * @param string $climits The JOIN clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) ); } $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : ''; $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : ''; $comments = (array) $wpdb->get_results("SELECT $distinct {$wpdb->comments}.* FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits"); // Convert to WP_Comment $this->comments = array_map( 'get_comment', $comments ); $this->comment_count = count($this->comments); $post_ids = array(); foreach ( $this->comments as $comment ) $post_ids[] = (int) $comment->comment_post_ID; $post_ids = join(',', $post_ids); $join = ''; if ( $post_ids ) { $where = "AND {$wpdb->posts}.ID IN ($post_ids) "; } else { $where = "AND 0"; } } $pieces = array( 'where', 'groupby', 'join', 'orderby', 'distinct', 'fields', 'limits' ); /* * Apply post-paging filters on where and join. Only plugins that * manipulate paging queries should use these hooks. */ if ( !$q['suppress_filters'] ) { /** * Filters the WHERE clause of the query. * * Specifically for manipulating paging queries. * * @since 1.5.0 * * @param string $where The WHERE clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $where = apply_filters_ref_array( 'posts_where_paged', array( $where, &$this ) ); /** * Filters the GROUP BY clause of the query. * * @since 2.0.0 * * @param string $groupby The GROUP BY clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $groupby = apply_filters_ref_array( 'posts_groupby', array( $groupby, &$this ) ); /** * Filters the JOIN clause of the query. * * Specifically for manipulating paging queries. * * @since 1.5.0 * * @param string $join The JOIN clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $join = apply_filters_ref_array( 'posts_join_paged', array( $join, &$this ) ); /** * Filters the ORDER BY clause of the query. * * @since 1.5.1 * * @param string $orderby The ORDER BY clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $orderby = apply_filters_ref_array( 'posts_orderby', array( $orderby, &$this ) ); /** * Filters the DISTINCT clause of the query. * * @since 2.1.0 * * @param string $distinct The DISTINCT clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $distinct = apply_filters_ref_array( 'posts_distinct', array( $distinct, &$this ) ); /** * Filters the LIMIT clause of the query. * * @since 2.1.0 * * @param string $limits The LIMIT clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $limits = apply_filters_ref_array( 'post_limits', array( $limits, &$this ) ); /** * Filters the SELECT clause of the query. * * @since 2.1.0 * * @param string $fields The SELECT clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $fields = apply_filters_ref_array( 'posts_fields', array( $fields, &$this ) ); /** * Filters all query clauses at once, for convenience. * * Covers the WHERE, GROUP BY, JOIN, ORDER BY, DISTINCT, * fields (SELECT), and LIMITS clauses. * * @since 3.1.0 * * @param array $clauses The list of clauses for the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) ); $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : ''; $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : ''; $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : ''; $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : ''; $distinct = isset( $clauses[ 'distinct' ] ) ? $clauses[ 'distinct' ] : ''; $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : ''; $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : ''; } /** * Fires to announce the query's current selection parameters. * * For use by caching plugins. * * @since 2.3.0 * * @param string $selection The assembled selection query. */ do_action( 'posts_selection', $where . $groupby . $orderby . $limits . $join ); /* * Filters again for the benefit of caching plugins. * Regular plugins should use the hooks above. */ if ( !$q['suppress_filters'] ) { /** * Filters the WHERE clause of the query. * * For use by caching plugins. * * @since 2.5.0 * * @param string $where The WHERE clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $where = apply_filters_ref_array( 'posts_where_request', array( $where, &$this ) ); /** * Filters the GROUP BY clause of the query. * * For use by caching plugins. * * @since 2.5.0 * * @param string $groupby The GROUP BY clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $groupby = apply_filters_ref_array( 'posts_groupby_request', array( $groupby, &$this ) ); /** * Filters the JOIN clause of the query. * * For use by caching plugins. * * @since 2.5.0 * * @param string $join The JOIN clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $join = apply_filters_ref_array( 'posts_join_request', array( $join, &$this ) ); /** * Filters the ORDER BY clause of the query. * * For use by caching plugins. * * @since 2.5.0 * * @param string $orderby The ORDER BY clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $orderby = apply_filters_ref_array( 'posts_orderby_request', array( $orderby, &$this ) ); /** * Filters the DISTINCT clause of the query. * * For use by caching plugins. * * @since 2.5.0 * * @param string $distinct The DISTINCT clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $distinct = apply_filters_ref_array( 'posts_distinct_request', array( $distinct, &$this ) ); /** * Filters the SELECT clause of the query. * * For use by caching plugins. * * @since 2.5.0 * * @param string $fields The SELECT clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $fields = apply_filters_ref_array( 'posts_fields_request', array( $fields, &$this ) ); /** * Filters the LIMIT clause of the query. * * For use by caching plugins. * * @since 2.5.0 * * @param string $limits The LIMIT clause of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $limits = apply_filters_ref_array( 'post_limits_request', array( $limits, &$this ) ); /** * Filters all query clauses at once, for convenience. * * For use by caching plugins. * * Covers the WHERE, GROUP BY, JOIN, ORDER BY, DISTINCT, * fields (SELECT), and LIMITS clauses. * * @since 3.1.0 * * @param array $pieces The pieces of the query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $pieces ), &$this ) ); $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : ''; $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : ''; $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : ''; $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : ''; $distinct = isset( $clauses[ 'distinct' ] ) ? $clauses[ 'distinct' ] : ''; $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : ''; $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : ''; } if ( ! empty($groupby) ) $groupby = 'GROUP BY ' . $groupby; if ( !empty( $orderby ) ) $orderby = 'ORDER BY ' . $orderby; $found_rows = ''; if ( !$q['no_found_rows'] && !empty($limits) ) $found_rows = 'SQL_CALC_FOUND_ROWS'; $this->request = $old_request = "SELECT $found_rows $distinct $fields FROM {$wpdb->posts} $join WHERE 1=1 $where $groupby $orderby $limits"; if ( !$q['suppress_filters'] ) { /** * Filters the completed SQL query before sending. * * @since 2.0.0 * * @param string $request The complete SQL query. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $this->request = apply_filters_ref_array( 'posts_request', array( $this->request, &$this ) ); } /** * Filters the posts array before the query takes place. * * Return a non-null value to bypass WordPress's default post queries. * * Filtering functions that require pagination information are encouraged to set * the `found_posts` and `max_num_pages` properties of the WP_Query object, * passed to the filter by reference. If WP_Query does not perform a database * query, it will not have enough information to generate these values itself. * * @since 4.6.0 * * @param array|null $posts Return an array of post data to short-circuit WP's query, * or null to allow WP to run its normal queries. * @param WP_Query $this The WP_Query instance, passed by reference. */ $this->posts = apply_filters_ref_array( 'posts_pre_query', array( null, &$this ) ); if ( 'ids' == $q['fields'] ) { if ( null === $this->posts ) { $this->posts = $wpdb->get_col( $this->request ); } $this->posts = array_map( 'intval', $this->posts ); $this->post_count = count( $this->posts ); $this->set_found_posts( $q, $limits ); return $this->posts; } if ( 'id=>parent' == $q['fields'] ) { if ( null === $this->posts ) { $this->posts = $wpdb->get_results( $this->request ); } $this->post_count = count( $this->posts ); $this->set_found_posts( $q, $limits ); $r = array(); foreach ( $this->posts as $key => $post ) { $this->posts[ $key ]->ID = (int) $post->ID; $this->posts[ $key ]->post_parent = (int) $post->post_parent; $r[ (int) $post->ID ] = (int) $post->post_parent; } return $r; } if ( null === $this->posts ) { $split_the_query = ( $old_request == $this->request && "{$wpdb->posts}.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 ); /** * Filters whether to split the query. * * Splitting the query will cause it to fetch just the IDs of the found posts * (and then individually fetch each post by ID), rather than fetching every * complete row at once. One massive result vs. many small results. * * @since 3.4.0 * * @param bool $split_the_query Whether or not to split the query. * @param WP_Query $this The WP_Query instance. */ $split_the_query = apply_filters( 'split_the_query', $split_the_query, $this ); if ( $split_the_query ) { // First get the IDs and then fill in the objects $this->request = "SELECT $found_rows $distinct {$wpdb->posts}.ID FROM {$wpdb->posts} $join WHERE 1=1 $where $groupby $orderby $limits"; /** * Filters the Post IDs SQL request before sending. * * @since 3.4.0 * * @param string $request The post ID request. * @param WP_Query $this The WP_Query instance. */ $this->request = apply_filters( 'posts_request_ids', $this->request, $this ); $ids = $wpdb->get_col( $this->request ); if ( $ids ) { $this->posts = $ids; $this->set_found_posts( $q, $limits ); _prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] ); } else { $this->posts = array(); } } else { $this->posts = $wpdb->get_results( $this->request ); $this->set_found_posts( $q, $limits ); } } // Convert to WP_Post objects. if ( $this->posts ) { $this->posts = array_map( 'get_post', $this->posts ); } if ( ! $q['suppress_filters'] ) { /** * Filters the raw post results array, prior to status checks. * * @since 2.3.0 * * @param array $posts The post results array. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $this->posts = apply_filters_ref_array( 'posts_results', array( $this->posts, &$this ) ); } if ( !empty($this->posts) && $this->is_comment_feed && $this->is_singular ) { /** This filter is documented in wp-includes/query.php */ $cjoin = apply_filters_ref_array( 'comment_feed_join', array( '', &$this ) ); /** This filter is documented in wp-includes/query.php */ $cwhere = apply_filters_ref_array( 'comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'", &$this ) ); /** This filter is documented in wp-includes/query.php */ $cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( '', &$this ) ); $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : ''; /** This filter is documented in wp-includes/query.php */ $corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) ); $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : ''; /** This filter is documented in wp-includes/query.php */ $climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) ); $comments_request = "SELECT {$wpdb->comments}.* FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits"; $comments = $wpdb->get_results($comments_request); // Convert to WP_Comment $this->comments = array_map( 'get_comment', $comments ); $this->comment_count = count($this->comments); } // Check post status to determine if post should be displayed. if ( !empty($this->posts) && ($this->is_single || $this->is_page) ) { $status = get_post_status($this->posts[0]); if ( 'attachment' === $this->posts[0]->post_type && 0 === (int) $this->posts[0]->post_parent ) { $this->is_page = false; $this->is_single = true; $this->is_attachment = true; } $post_status_obj = get_post_status_object($status); // If the post_status was specifically requested, let it pass through. if ( !$post_status_obj->public && ! in_array( $status, $q_status ) ) { if ( ! is_user_logged_in() ) { // User must be logged in to view unpublished posts. $this->posts = array(); } else { if ( $post_status_obj->protected ) { // User must have edit permissions on the draft to preview. if ( ! current_user_can($edit_cap, $this->posts[0]->ID) ) { $this->posts = array(); } else { $this->is_preview = true; if ( 'future' != $status ) $this->posts[0]->post_date = current_time('mysql'); } } elseif ( $post_status_obj->private ) { if ( ! current_user_can($read_cap, $this->posts[0]->ID) ) $this->posts = array(); } else { $this->posts = array(); } } } if ( $this->is_preview && $this->posts && current_user_can( $edit_cap, $this->posts[0]->ID ) ) { /** * Filters the single post for preview mode. * * @since 2.7.0 * * @param WP_Post $post_preview The Post object. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $this->posts[0] = get_post( apply_filters_ref_array( 'the_preview', array( $this->posts[0], &$this ) ) ); } } // Put sticky posts at the top of the posts array $sticky_posts = get_option('sticky_posts'); if ( $this->is_home && $page <= 1 && is_array($sticky_posts) && !empty($sticky_posts) && !$q['ignore_sticky_posts'] ) { $num_posts = count($this->posts); $sticky_offset = 0; // Loop over posts and relocate stickies to the front. for ( $i = 0; $i < $num_posts; $i++ ) { if ( in_array($this->posts[$i]->ID, $sticky_posts) ) { $sticky_post = $this->posts[$i]; // Remove sticky from current position array_splice($this->posts, $i, 1); // Move to front, after other stickies array_splice($this->posts, $sticky_offset, 0, array($sticky_post)); // Increment the sticky offset. The next sticky will be placed at this offset. $sticky_offset++; // Remove post from sticky posts array $offset = array_search($sticky_post->ID, $sticky_posts); unset( $sticky_posts[$offset] ); } } // If any posts have been excluded specifically, Ignore those that are sticky. if ( !empty($sticky_posts) && !empty($q['post__not_in']) ) $sticky_posts = array_diff($sticky_posts, $q['post__not_in']); // Fetch sticky posts that weren't in the query results if ( !empty($sticky_posts) ) { $stickies = get_posts( array( 'post__in' => $sticky_posts, 'post_type' => $post_type, 'post_status' => 'publish', 'nopaging' => true ) ); foreach ( $stickies as $sticky_post ) { array_splice( $this->posts, $sticky_offset, 0, array( $sticky_post ) ); $sticky_offset++; } } } // If comments have been fetched as part of the query, make sure comment meta lazy-loading is set up. if ( ! empty( $this->comments ) ) { wp_queue_comments_for_comment_meta_lazyload( $this->comments ); } if ( ! $q['suppress_filters'] ) { /** * Filters the array of retrieved posts after they've been fetched and * internally processed. * * @since 1.5.0 * * @param array $posts The array of retrieved posts. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $this->posts = apply_filters_ref_array( 'the_posts', array( $this->posts, &$this ) ); } // Ensure that any posts added/modified via one of the filters above are // of the type WP_Post and are filtered. if ( $this->posts ) { $this->post_count = count( $this->posts ); $this->posts = array_map( 'get_post', $this->posts ); if ( $q['cache_results'] ) update_post_caches($this->posts, $post_type, $q['update_post_term_cache'], $q['update_post_meta_cache']); $this->post = reset( $this->posts ); } else { $this->post_count = 0; $this->posts = array(); } if ( $q['lazy_load_term_meta'] ) { wp_queue_posts_for_term_meta_lazyload( $this->posts ); } return $this->posts; } /** * Set up the amount of found posts and the number of pages (if limit clause was used) * for the current query. * * @since 3.5.0 * @access private * * @param array $q Query variables. * @param string $limits LIMIT clauses of the query. */ private function set_found_posts( $q, $limits ) { global $wpdb; // Bail if posts is an empty array. Continue if posts is an empty string, // null, or false to accommodate caching plugins that fill posts later. if ( $q['no_found_rows'] || ( is_array( $this->posts ) && ! $this->posts ) ) return; if ( ! empty( $limits ) ) { /** * Filters the query to run for retrieving the found posts. * * @since 2.1.0 * * @param string $found_posts The query to run to find the found posts. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $this->found_posts = $wpdb->get_var( apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) ) ); } else { $this->found_posts = count( $this->posts ); } /** * Filters the number of found posts for the query. * * @since 2.1.0 * * @param int $found_posts The number of posts found. * @param WP_Query &$this The WP_Query instance (passed by reference). */ $this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) ); if ( ! empty( $limits ) ) $this->max_num_pages = ceil( $this->found_posts / $q['posts_per_page'] ); } /** * Set up the next post and iterate current post index. * * @since 1.5.0 * @access public * * @return WP_Post Next post. */ public function next_post() { $this->current_post++; $this->post = $this->posts[$this->current_post]; return $this->post; } /** * Sets up the current post. * * Retrieves the next post, sets up the post, sets the 'in the loop' * property to true. * * @since 1.5.0 * @access public * * @global WP_Post $post */ public function the_post() { global $post; $this->in_the_loop = true; if ( $this->current_post == -1 ) // loop has just started /** * Fires once the loop is started. * * @since 2.0.0 * * @param WP_Query &$this The WP_Query instance (passed by reference). */ do_action_ref_array( 'loop_start', array( &$this ) ); $post = $this->next_post(); $this->setup_postdata( $post ); } /** * Determines whether there are more posts available in the loop. * * Calls the {@see 'loop_end'} action when the loop is complete. * * @since 1.5.0 * @access public * * @return bool True if posts are available, false if end of loop. */ public function have_posts() { if ( $this->current_post + 1 < $this->post_count ) { return true; } elseif ( $this->current_post + 1 == $this->post_count && $this->post_count > 0 ) { /** * Fires once the loop has ended. * * @since 2.0.0 * * @param WP_Query &$this The WP_Query instance (passed by reference). */ do_action_ref_array( 'loop_end', array( &$this ) ); // Do some cleaning up after the loop $this->rewind_posts(); } $this->in_the_loop = false; return false; } /** * Rewind the posts and reset post index. * * @since 1.5.0 * @access public */ public function rewind_posts() { $this->current_post = -1; if ( $this->post_count > 0 ) { $this->post = $this->posts[0]; } } /** * Iterate current comment index and return WP_Comment object. * * @since 2.2.0 * @access public * * @return WP_Comment Comment object. */ public function next_comment() { $this->current_comment++; $this->comment = $this->comments[$this->current_comment]; return $this->comment; } /** * Sets up the current comment. * * @since 2.2.0 * @access public * @global WP_Comment $comment Current comment. */ public function the_comment() { global $comment; $comment = $this->next_comment(); if ( $this->current_comment == 0 ) { /** * Fires once the comment loop is started. * * @since 2.2.0 */ do_action( 'comment_loop_start' ); } } /** * Whether there are more comments available. * * Automatically rewinds comments when finished. * * @since 2.2.0 * @access public * * @return bool True, if more comments. False, if no more posts. */ public function have_comments() { if ( $this->current_comment + 1 < $this->comment_count ) { return true; } elseif ( $this->current_comment + 1 == $this->comment_count ) { $this->rewind_comments(); } return false; } /** * Rewind the comments, resets the comment index and comment to first. * * @since 2.2.0 * @access public */ public function rewind_comments() { $this->current_comment = -1; if ( $this->comment_count > 0 ) { $this->comment = $this->comments[0]; } } /** * Sets up the WordPress query by parsing query string. * * @since 1.5.0 * @access public * * @param string $query URL query string. * @return array List of posts. */ public function query( $query ) { $this->init(); $this->query = $this->query_vars = wp_parse_args( $query ); return $this->get_posts(); } /** * Retrieve queried object. * * If queried object is not set, then the queried object will be set from * the category, tag, taxonomy, posts page, single post, page, or author * query variable. After it is set up, it will be returned. * * @since 1.5.0 * @access public * * @return object */ public function get_queried_object() { if ( isset($this->queried_object) ) return $this->queried_object; $this->queried_object = null; $this->queried_object_id = null; if ( $this->is_category || $this->is_tag || $this->is_tax ) { if ( $this->is_category ) { if ( $this->get( 'cat' ) ) { $term = get_term( $this->get( 'cat' ), 'category' ); } elseif ( $this->get( 'category_name' ) ) { $term = get_term_by( 'slug', $this->get( 'category_name' ), 'category' ); } } elseif ( $this->is_tag ) { if ( $this->get( 'tag_id' ) ) { $term = get_term( $this->get( 'tag_id' ), 'post_tag' ); } elseif ( $this->get( 'tag' ) ) { $term = get_term_by( 'slug', $this->get( 'tag' ), 'post_tag' ); } } else { // For other tax queries, grab the first term from the first clause. if ( ! empty( $this->tax_query->queried_terms ) ) { $queried_taxonomies = array_keys( $this->tax_query->queried_terms ); $matched_taxonomy = reset( $queried_taxonomies ); $query = $this->tax_query->queried_terms[ $matched_taxonomy ]; if ( ! empty( $query['terms'] ) ) { if ( 'term_id' == $query['field'] ) { $term = get_term( reset( $query['terms'] ), $matched_taxonomy ); } else { $term = get_term_by( $query['field'], reset( $query['terms'] ), $matched_taxonomy ); } } } } if ( ! empty( $term ) && ! is_wp_error( $term ) ) { $this->queried_object = $term; $this->queried_object_id = (int) $term->term_id; if ( $this->is_category && 'category' === $this->queried_object->taxonomy ) _make_cat_compat( $this->queried_object ); } } elseif ( $this->is_post_type_archive ) { $post_type = $this->get( 'post_type' ); if ( is_array( $post_type ) ) $post_type = reset( $post_type ); $this->queried_object = get_post_type_object( $post_type ); } elseif ( $this->is_posts_page ) { $page_for_posts = get_option('page_for_posts'); $this->queried_object = get_post( $page_for_posts ); $this->queried_object_id = (int) $this->queried_object->ID; } elseif ( $this->is_singular && ! empty( $this->post ) ) { $this->queried_object = $this->post; $this->queried_object_id = (int) $this->post->ID; } elseif ( $this->is_author ) { $this->queried_object_id = (int) $this->get('author'); $this->queried_object = get_userdata( $this->queried_object_id ); } return $this->queried_object; } /** * Retrieve ID of the current queried object. * * @since 1.5.0 * @access public * * @return int */ public function get_queried_object_id() { $this->get_queried_object(); if ( isset($this->queried_object_id) ) { return $this->queried_object_id; } return 0; } /** * Constructor. * * Sets up the WordPress query, if parameter is not empty. * * @since 1.5.0 * @access public * * @param string|array $query URL query string or array of vars. */ public function __construct( $query = '' ) { if ( ! empty( $query ) ) { $this->query( $query ); } } /** * Make private properties readable for backward compatibility. * * @since 4.0.0 * @access public * * @param string $name Property to get. * @return mixed Property. */ public function __get( $name ) { if ( in_array( $name, $this->compat_fields ) ) { return $this->$name; } } /** * Make private properties checkable for backward compatibility. * * @since 4.0.0 * @access public * * @param string $name Property to check if set. * @return bool Whether the property is set. */ public function __isset( $name ) { if ( in_array( $name, $this->compat_fields ) ) { return isset( $this->$name ); } } /** * Make private/protected methods readable for backward compatibility. * * @since 4.0.0 * @access public * * @param callable $name Method to call. * @param array $arguments Arguments to pass when calling. * @return mixed|false Return value of the callback, false otherwise. */ public function __call( $name, $arguments ) { if ( in_array( $name, $this->compat_methods ) ) { return call_user_func_array( array( $this, $name ), $arguments ); } return false; } /** * Is the query for an existing archive page? * * Month, Year, Category, Author, Post Type archive... * * @since 3.1.0 * * @return bool */ public function is_archive() { return (bool) $this->is_archive; } /** * Is the query for an existing post type archive page? * * @since 3.1.0 * * @param mixed $post_types Optional. Post type or array of posts types to check against. * @return bool */ public function is_post_type_archive( $post_types = '' ) { if ( empty( $post_types ) || ! $this->is_post_type_archive ) return (bool) $this->is_post_type_archive; $post_type = $this->get( 'post_type' ); if ( is_array( $post_type ) ) $post_type = reset( $post_type ); $post_type_object = get_post_type_object( $post_type ); return in_array( $post_type_object->name, (array) $post_types ); } /** * Is the query for an existing attachment page? * * @since 3.1.0 * * @param mixed $attachment Attachment ID, title, slug, or array of such. * @return bool */ public function is_attachment( $attachment = '' ) { if ( ! $this->is_attachment ) { return false; } if ( empty( $attachment ) ) { return true; } $attachment = array_map( 'strval', (array) $attachment ); $post_obj = $this->get_queried_object(); if ( in_array( (string) $post_obj->ID, $attachment ) ) { return true; } elseif ( in_array( $post_obj->post_title, $attachment ) ) { return true; } elseif ( in_array( $post_obj->post_name, $attachment ) ) { return true; } return false; } /** * Is the query for an existing author archive page? * * If the $author parameter is specified, this function will additionally * check if the query is for one of the authors specified. * * @since 3.1.0 * * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames * @return bool */ public function is_author( $author = '' ) { if ( !$this->is_author ) return false; if ( empty($author) ) return true; $author_obj = $this->get_queried_object(); $author = array_map( 'strval', (array) $author ); if ( in_array( (string) $author_obj->ID, $author ) ) return true; elseif ( in_array( $author_obj->nickname, $author ) ) return true; elseif ( in_array( $author_obj->user_nicename, $author ) ) return true; return false; } /** * Is the query for an existing category archive page? * * If the $category parameter is specified, this function will additionally * check if the query is for one of the categories specified. * * @since 3.1.0 * * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs. * @return bool */ public function is_category( $category = '' ) { if ( !$this->is_category ) return false; if ( empty($category) ) return true; $cat_obj = $this->get_queried_object(); $category = array_map( 'strval', (array) $category ); if ( in_array( (string) $cat_obj->term_id, $category ) ) return true; elseif ( in_array( $cat_obj->name, $category ) ) return true; elseif ( in_array( $cat_obj->slug, $category ) ) return true; return false; } /** * Is the query for an existing tag archive page? * * If the $tag parameter is specified, this function will additionally * check if the query is for one of the tags specified. * * @since 3.1.0 * * @param mixed $tag Optional. Tag ID, name, slug, or array of Tag IDs, names, and slugs. * @return bool */ public function is_tag( $tag = '' ) { if ( ! $this->is_tag ) return false; if ( empty( $tag ) ) return true; $tag_obj = $this->get_queried_object(); $tag = array_map( 'strval', (array) $tag ); if ( in_array( (string) $tag_obj->term_id, $tag ) ) return true; elseif ( in_array( $tag_obj->name, $tag ) ) return true; elseif ( in_array( $tag_obj->slug, $tag ) ) return true; return false; } /** * Is the query for an existing custom taxonomy archive page? * * If the $taxonomy parameter is specified, this function will additionally * check if the query is for that specific $taxonomy. * * If the $term parameter is specified in addition to the $taxonomy parameter, * this function will additionally check if the query is for one of the terms * specified. * * @since 3.1.0 * * @global array $wp_taxonomies * * @param mixed $taxonomy Optional. Taxonomy slug or slugs. * @param mixed $term Optional. Term ID, name, slug or array of Term IDs, names, and slugs. * @return bool True for custom taxonomy archive pages, false for built-in taxonomies (category and tag archives). */ public function is_tax( $taxonomy = '', $term = '' ) { global $wp_taxonomies; if ( !$this->is_tax ) return false; if ( empty( $taxonomy ) ) return true; $queried_object = $this->get_queried_object(); $tax_array = array_intersect( array_keys( $wp_taxonomies ), (array) $taxonomy ); $term_array = (array) $term; // Check that the taxonomy matches. if ( ! ( isset( $queried_object->taxonomy ) && count( $tax_array ) && in_array( $queried_object->taxonomy, $tax_array ) ) ) return false; // Only a Taxonomy provided. if ( empty( $term ) ) return true; return isset( $queried_object->term_id ) && count( array_intersect( array( $queried_object->term_id, $queried_object->name, $queried_object->slug ), $term_array ) ); } /** * Whether the current URL is within the comments popup window. * * @since 3.1.0 * @deprecated 4.5.0 * * @return bool */ public function is_comments_popup() { _deprecated_function( __FUNCTION__, '4.5.0' ); return false; } /** * Is the query for an existing date archive? * * @since 3.1.0 * * @return bool */ public function is_date() { return (bool) $this->is_date; } /** * Is the query for an existing day archive? * * @since 3.1.0 * * @return bool */ public function is_day() { return (bool) $this->is_day; } /** * Is the query for a feed? * * @since 3.1.0 * * @param string|array $feeds Optional feed types to check. * @return bool */ public function is_feed( $feeds = '' ) { if ( empty( $feeds ) || ! $this->is_feed ) return (bool) $this->is_feed; $qv = $this->get( 'feed' ); if ( 'feed' == $qv ) $qv = get_default_feed(); return in_array( $qv, (array) $feeds ); } /** * Is the query for a comments feed? * * @since 3.1.0 * * @return bool */ public function is_comment_feed() { return (bool) $this->is_comment_feed; } /** * Is the query for the front page of the site? * * This is for what is displayed at your site's main URL. * * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'. * * If you set a static page for the front page of your site, this function will return * true when viewing that page. * * Otherwise the same as @see WP_Query::is_home() * * @since 3.1.0 * * @return bool True, if front of site. */ public function is_front_page() { // most likely case if ( 'posts' == get_option( 'show_on_front') && $this->is_home() ) return true; elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) ) return true; else return false; } /** * Is the query for the blog homepage? * * This is the page which shows the time based blog content of your site. * * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'. * * If you set a static page for the front page of your site, this function will return * true only on the page you set as the "Posts page". * * @see WP_Query::is_front_page() * * @since 3.1.0 * * @return bool True if blog view homepage. */ public function is_home() { return (bool) $this->is_home; } /** * Is the query for an existing month archive? * * @since 3.1.0 * * @return bool */ public function is_month() { return (bool) $this->is_month; } /** * Is the query for an existing single page? * * If the $page parameter is specified, this function will additionally * check if the query is for one of the pages specified. * * @see WP_Query::is_single() * @see WP_Query::is_singular() * * @since 3.1.0 * * @param int|string|array $page Optional. Page ID, title, slug, path, or array of such. Default empty. * @return bool Whether the query is for an existing single page. */ public function is_page( $page = '' ) { if ( !$this->is_page ) return false; if ( empty( $page ) ) return true; $page_obj = $this->get_queried_object(); $page = array_map( 'strval', (array) $page ); if ( in_array( (string) $page_obj->ID, $page ) ) { return true; } elseif ( in_array( $page_obj->post_title, $page ) ) { return true; } elseif ( in_array( $page_obj->post_name, $page ) ) { return true; } else { foreach ( $page as $pagepath ) { if ( ! strpos( $pagepath, '/' ) ) { continue; } $pagepath_obj = get_page_by_path( $pagepath ); if ( $pagepath_obj && ( $pagepath_obj->ID == $page_obj->ID ) ) { return true; } } } return false; } /** * Is the query for paged result and not for the first page? * * @since 3.1.0 * * @return bool */ public function is_paged() { return (bool) $this->is_paged; } /** * Is the query for a post or page preview? * * @since 3.1.0 * * @return bool */ public function is_preview() { return (bool) $this->is_preview; } /** * Is the query for the robots file? * * @since 3.1.0 * * @return bool */ public function is_robots() { return (bool) $this->is_robots; } /** * Is the query for a search? * * @since 3.1.0 * * @return bool */ public function is_search() { return (bool) $this->is_search; } /** * Is the query for an existing single post? * * Works for any post type excluding pages. * * If the $post parameter is specified, this function will additionally * check if the query is for one of the Posts specified. * * @see WP_Query::is_page() * @see WP_Query::is_singular() * * @since 3.1.0 * * @param int|string|array $post Optional. Post ID, title, slug, path, or array of such. Default empty. * @return bool Whether the query is for an existing single post. */ public function is_single( $post = '' ) { if ( !$this->is_single ) return false; if ( empty($post) ) return true; $post_obj = $this->get_queried_object(); $post = array_map( 'strval', (array) $post ); if ( in_array( (string) $post_obj->ID, $post ) ) { return true; } elseif ( in_array( $post_obj->post_title, $post ) ) { return true; } elseif ( in_array( $post_obj->post_name, $post ) ) { return true; } else { foreach ( $post as $postpath ) { if ( ! strpos( $postpath, '/' ) ) { continue; } $postpath_obj = get_page_by_path( $postpath, OBJECT, $post_obj->post_type ); if ( $postpath_obj && ( $postpath_obj->ID == $post_obj->ID ) ) { return true; } } } return false; } /** * Is the query for an existing single post of any post type (post, attachment, page, ... )? * * If the $post_types parameter is specified, this function will additionally * check if the query is for one of the Posts Types specified. * * @see WP_Query::is_page() * @see WP_Query::is_single() * * @since 3.1.0 * * @param string|array $post_types Optional. Post type or array of post types. Default empty. * @return bool Whether the query is for an existing single post of any of the given post types. */ public function is_singular( $post_types = '' ) { if ( empty( $post_types ) || !$this->is_singular ) return (bool) $this->is_singular; $post_obj = $this->get_queried_object(); return in_array( $post_obj->post_type, (array) $post_types ); } /** * Is the query for a specific time? * * @since 3.1.0 * * @return bool */ public function is_time() { return (bool) $this->is_time; } /** * Is the query for a trackback endpoint call? * * @since 3.1.0 * * @return bool */ public function is_trackback() { return (bool) $this->is_trackback; } /** * Is the query for an existing year archive? * * @since 3.1.0 * * @return bool */ public function is_year() { return (bool) $this->is_year; } /** * Is the query a 404 (returns no results)? * * @since 3.1.0 * * @return bool */ public function is_404() { return (bool) $this->is_404; } /** * Is the query for an embedded post? * * @since 4.4.0 * * @return bool */ public function is_embed() { return (bool) $this->is_embed; } /** * Is the query the main query? * * @since 3.3.0 * * @global WP_Query $wp_query Global WP_Query instance. * * @return bool */ public function is_main_query() { global $wp_the_query; return $wp_the_query === $this; } /** * Set up global post data. * * @since 4.1.0 * @since 4.4.0 Added the ability to pass a post ID to `$post`. * * @global int $id * @global WP_User $authordata * @global string|int|bool $currentday * @global string|int|bool $currentmonth * @global int $page * @global array $pages * @global int $multipage * @global int $more * @global int $numpages * * @param WP_Post|object|int $post WP_Post instance or Post ID/object. * @return true True when finished. */ public function setup_postdata( $post ) { global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages; if ( ! ( $post instanceof WP_Post ) ) { $post = get_post( $post ); } if ( ! $post ) { return; } $id = (int) $post->ID; $authordata = get_userdata($post->post_author); $currentday = mysql2date('d.m.y', $post->post_date, false); $currentmonth = mysql2date('m', $post->post_date, false); $numpages = 1; $multipage = 0; $page = $this->get( 'page' ); if ( ! $page ) $page = 1; /* * Force full post content when viewing the permalink for the $post, * or when on an RSS feed. Otherwise respect the 'more' tag. */ if ( $post->ID === get_queried_object_id() && ( $this->is_page() || $this->is_single() ) ) { $more = 1; } elseif ( $this->is_feed() ) { $more = 1; } else { $more = 0; } $content = $post->post_content; if ( false !== strpos( $content, '' ) ) { $content = str_replace( "\n\n", '', $content ); $content = str_replace( "\n", '', $content ); $content = str_replace( "\n", '', $content ); // Ignore nextpage at the beginning of the content. if ( 0 === strpos( $content, '' ) ) $content = substr( $content, 15 ); $pages = explode('', $content); } else { $pages = array( $post->post_content ); } /** * Filters the "pages" derived from splitting the post content. * * "Pages" are determined by splitting the post content based on the presence * of `` tags. * * @since 4.4.0 * * @param array $pages Array of "pages" derived from the post content. * of `` tags.. * @param WP_Post $post Current post object. */ $pages = apply_filters( 'content_pagination', $pages, $post ); $numpages = count( $pages ); if ( $numpages > 1 ) { if ( $page > 1 ) { $more = 1; } $multipage = 1; } else { $multipage = 0; } /** * Fires once the post data has been setup. * * @since 2.8.0 * @since 4.1.0 Introduced `$this` parameter. * * @param WP_Post &$post The Post object (passed by reference). * @param WP_Query &$this The current Query object (passed by reference). */ do_action_ref_array( 'the_post', array( &$post, &$this ) ); return true; } /** * After looping through a nested query, this function * restores the $post global to the current post in this query. * * @since 3.7.0 * * @global WP_Post $post */ public function reset_postdata() { if ( ! empty( $this->post ) ) { $GLOBALS['post'] = $this->post; $this->setup_postdata( $this->post ); } } /** * Lazyload term meta for posts in the loop. * * @since 4.4.0 * @deprecated 4.5.0 See wp_queue_posts_for_term_meta_lazyload(). * * @param mixed $check * @param int $term_id * @return mixed */ public function lazyload_term_meta( $check, $term_id ) { _deprecated_function( __METHOD__, '4.5.0' ); return $check; } /** * Lazyload comment meta for comments in the loop. * * @since 4.4.0 * @deprecated 4.5.0 See wp_queue_comments_for_comment_meta_lazyload(). * * @param mixed $check * @param int $comment_id * @return mixed */ public function lazyload_comment_meta( $check, $comment_id ) { _deprecated_function( __METHOD__, '4.5.0' ); return $check; } } /** * Deprecated functions from past WordPress versions. You shouldn't use these * functions and look for the alternatives instead. The functions will be * removed in a later version. * * @package WordPress * @subpackage Deprecated */ /* * Deprecated functions come here to die. */ /** * Retrieves all post data for a given post. * * @since 0.71 * @deprecated 1.5.1 Use get_post() * @see get_post() * * @param int $postid Post ID. * @return array Post data. */ function get_postdata($postid) { _deprecated_function( __FUNCTION__, '1.5.1', 'get_post()' ); $post = get_post($postid); $postdata = array ( 'ID' => $post->ID, 'Author_ID' => $post->post_author, 'Date' => $post->post_date, 'Content' => $post->post_content, 'Excerpt' => $post->post_excerpt, 'Title' => $post->post_title, 'Category' => $post->post_category, 'post_status' => $post->post_status, 'comment_status' => $post->comment_status, 'ping_status' => $post->ping_status, 'post_password' => $post->post_password, 'to_ping' => $post->to_ping, 'pinged' => $post->pinged, 'post_type' => $post->post_type, 'post_name' => $post->post_name ); return $postdata; } /** * Sets up the WordPress Loop. * * Use The Loop instead. * * @link https://codex.wordpress.org/The_Loop * * @since 1.0.1 * @deprecated 1.5.0 */ function start_wp() { global $wp_query; _deprecated_function( __FUNCTION__, '1.5.0', __('new WordPress Loop') ); // Since the old style loop is being used, advance the query iterator here. $wp_query->next_post(); setup_postdata( get_post() ); } /** * Returns or prints a category ID. * * @since 0.71 * @deprecated 0.71 Use get_the_category() * @see get_the_category() * * @param bool $echo Optional. Whether to echo the output. Default true. * @return int Category ID. */ function the_category_ID($echo = true) { _deprecated_function( __FUNCTION__, '0.71', 'get_the_category()' ); // Grab the first cat in the list. $categories = get_the_category(); $cat = $categories[0]->term_id; if ( $echo ) echo $cat; return $cat; } /** * Prints a category with optional text before and after. * * @since 0.71 * @deprecated 0.71 Use get_the_category_by_ID() * @see get_the_category_by_ID() * * @param string $before Optional. Text to display before the category. Default empty. * @param string $after Optional. Text to display after the category. Default empty. */ function the_category_head( $before = '', $after = '' ) { global $currentcat, $previouscat; _deprecated_function( __FUNCTION__, '0.71', 'get_the_category_by_ID()' ); // Grab the first cat in the list. $categories = get_the_category(); $currentcat = $categories[0]->category_id; if ( $currentcat != $previouscat ) { echo $before; echo get_the_category_by_ID($currentcat); echo $after; $previouscat = $currentcat; } } /** * Prints a link to the previous post. * * @since 1.5.0 * @deprecated 2.0.0 Use previous_post_link() * @see previous_post_link() * * @param string $format * @param string $previous * @param string $title * @param string $in_same_cat * @param int $limitprev * @param string $excluded_categories */ function previous_post($format='%', $previous='previous post: ', $title='yes', $in_same_cat='no', $limitprev=1, $excluded_categories='') { _deprecated_function( __FUNCTION__, '2.0.0', 'previous_post_link()' ); if ( empty($in_same_cat) || 'no' == $in_same_cat ) $in_same_cat = false; else $in_same_cat = true; $post = get_previous_post($in_same_cat, $excluded_categories); if ( !$post ) return; $string = ''.$previous; if ( 'yes' == $title ) $string .= apply_filters('the_title', $post->post_title, $post->ID); $string .= ''; $format = str_replace('%', $string, $format); echo $format; } /** * Prints link to the next post. * * @since 0.71 * @deprecated 2.0.0 Use next_post_link() * @see next_post_link() * * @param string $format * @param string $next * @param string $title * @param string $in_same_cat * @param int $limitnext * @param string $excluded_categories */ function next_post($format='%', $next='next post: ', $title='yes', $in_same_cat='no', $limitnext=1, $excluded_categories='') { _deprecated_function( __FUNCTION__, '2.0.0', 'next_post_link()' ); if ( empty($in_same_cat) || 'no' == $in_same_cat ) $in_same_cat = false; else $in_same_cat = true; $post = get_next_post($in_same_cat, $excluded_categories); if ( !$post ) return; $string = ''.$next; if ( 'yes' == $title ) $string .= apply_filters('the_title', $post->post_title, $post->ID); $string .= ''; $format = str_replace('%', $string, $format); echo $format; } /** * Whether user can create a post. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $blog_id Not Used * @param int $category_id Not Used * @return bool */ function user_can_create_post($user_id, $blog_id = 1, $category_id = 'None') { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); $author_data = get_userdata($user_id); return ($author_data->user_level > 1); } /** * Whether user can create a post. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $blog_id Not Used * @param int $category_id Not Used * @return bool */ function user_can_create_draft($user_id, $blog_id = 1, $category_id = 'None') { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); $author_data = get_userdata($user_id); return ($author_data->user_level >= 1); } /** * Whether user can edit a post. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $post_id * @param int $blog_id Not Used * @return bool */ function user_can_edit_post($user_id, $post_id, $blog_id = 1) { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); $author_data = get_userdata($user_id); $post = get_post($post_id); $post_author_data = get_userdata($post->post_author); if ( (($user_id == $post_author_data->ID) && !($post->post_status == 'publish' && $author_data->user_level < 2)) || ($author_data->user_level > $post_author_data->user_level) || ($author_data->user_level >= 10) ) { return true; } else { return false; } } /** * Whether user can delete a post. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $post_id * @param int $blog_id Not Used * @return bool */ function user_can_delete_post($user_id, $post_id, $blog_id = 1) { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); // right now if one can edit, one can delete return user_can_edit_post($user_id, $post_id, $blog_id); } /** * Whether user can set new posts' dates. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $blog_id Not Used * @param int $category_id Not Used * @return bool */ function user_can_set_post_date($user_id, $blog_id = 1, $category_id = 'None') { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); $author_data = get_userdata($user_id); return (($author_data->user_level > 4) && user_can_create_post($user_id, $blog_id, $category_id)); } /** * Whether user can delete a post. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $post_id * @param int $blog_id Not Used * @return bool returns true if $user_id can edit $post_id's date */ function user_can_edit_post_date($user_id, $post_id, $blog_id = 1) { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); $author_data = get_userdata($user_id); return (($author_data->user_level > 4) && user_can_edit_post($user_id, $post_id, $blog_id)); } /** * Whether user can delete a post. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $post_id * @param int $blog_id Not Used * @return bool returns true if $user_id can edit $post_id's comments */ function user_can_edit_post_comments($user_id, $post_id, $blog_id = 1) { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); // right now if one can edit a post, one can edit comments made on it return user_can_edit_post($user_id, $post_id, $blog_id); } /** * Whether user can delete a post. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $post_id * @param int $blog_id Not Used * @return bool returns true if $user_id can delete $post_id's comments */ function user_can_delete_post_comments($user_id, $post_id, $blog_id = 1) { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); // right now if one can edit comments, one can delete comments return user_can_edit_post_comments($user_id, $post_id, $blog_id); } /** * Can user can edit other user. * * @since 1.5.0 * @deprecated 2.0.0 Use current_user_can() * @see current_user_can() * * @param int $user_id * @param int $other_user * @return bool */ function user_can_edit_user($user_id, $other_user) { _deprecated_function( __FUNCTION__, '2.0.0', 'current_user_can()' ); $user = get_userdata($user_id); $other = get_userdata($other_user); if ( $user->user_level > $other->user_level || $user->user_level > 8 || $user->ID == $other->ID ) return true; else return false; } /** * Gets the links associated with category $cat_name. * * @since 0.71 * @deprecated 2.1.0 Use get_bookmarks() * @see get_bookmarks() * * @param string $cat_name Optional. The category name to use. If no match is found uses all. * @param string $before Optional. The html to output before the link. * @param string $after Optional. The html to output after the link. * @param string $between Optional. The html to output between the link/image and its description. Not used if no image or $show_images is true. * @param bool $show_images Optional. Whether to show images (if defined). * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', 'description' or 'rating'. Or maybe owner. * If you start the name with an underscore the order will be reversed. You can also specify 'rand' as the order which will return links in a * random order. * @param bool $show_description Optional. Whether to show the description if show_images=false/not defined. * @param bool $show_rating Optional. Show rating stars/chars. * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. * @param int $show_updated Optional. Whether to show last updated timestamp */ function get_linksbyname($cat_name = "noname", $before = '', $after = '
', $between = " ", $show_images = true, $orderby = 'id', $show_description = true, $show_rating = false, $limit = -1, $show_updated = 0) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmarks()' ); $cat_id = -1; $cat = get_term_by('name', $cat_name, 'link_category'); if ( $cat ) $cat_id = $cat->term_id; get_links($cat_id, $before, $after, $between, $show_images, $orderby, $show_description, $show_rating, $limit, $show_updated); } /** * Gets the links associated with the named category. * * @since 1.0.1 * @deprecated 2.1.0 Use wp_list_bookmarks() * @see wp_list_bookmarks() * * @param string $category The category to use. * @param string $args * @return string|null */ function wp_get_linksbyname($category, $args = '') { _deprecated_function(__FUNCTION__, '2.1.0', 'wp_list_bookmarks()'); $defaults = array( 'after' => '
', 'before' => '', 'categorize' => 0, 'category_after' => '', 'category_before' => '', 'category_name' => $category, 'show_description' => 1, 'title_li' => '', ); $r = wp_parse_args( $args, $defaults ); return wp_list_bookmarks($r); } /** * Gets an array of link objects associated with category $cat_name. * * $links = get_linkobjectsbyname( 'fred' ); * foreach ( $links as $link ) { * echo '
  • ' . $link->link_name . '
  • '; * } * * @since 1.0.1 * @deprecated 2.1.0 Use get_bookmarks() * @see get_bookmarks() * * @param string $cat_name The category name to use. If no match is found uses all. * @param string $orderby The order to output the links. E.g. 'id', 'name', 'url', 'description', or 'rating'. * Or maybe owner. If you start the name with an underscore the order will be reversed. You can also * specify 'rand' as the order which will return links in a random order. * @param int $limit Limit to X entries. If not specified, all entries are shown. * @return array */ function get_linkobjectsbyname($cat_name = "noname" , $orderby = 'name', $limit = -1) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmarks()' ); $cat_id = -1; $cat = get_term_by('name', $cat_name, 'link_category'); if ( $cat ) $cat_id = $cat->term_id; return get_linkobjects($cat_id, $orderby, $limit); } /** * Gets an array of link objects associated with category n. * * Usage: * * $links = get_linkobjects(1); * if ($links) { * foreach ($links as $link) { * echo '
  • '.$link->link_name.'
    '.$link->link_description.'
  • '; * } * } * * Fields are: * * - link_id * - link_url * - link_name * - link_image * - link_target * - link_category * - link_description * - link_visible * - link_owner * - link_rating * - link_updated * - link_rel * - link_notes * * @since 1.0.1 * @deprecated 2.1.0 Use get_bookmarks() * @see get_bookmarks() * * @param int $category The category to use. If no category supplied uses all * @param string $orderby the order to output the links. E.g. 'id', 'name', 'url', * 'description', or 'rating'. Or maybe owner. If you start the name with an * underscore the order will be reversed. You can also specify 'rand' as the * order which will return links in a random order. * @param int $limit Limit to X entries. If not specified, all entries are shown. * @return array */ function get_linkobjects($category = 0, $orderby = 'name', $limit = 0) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmarks()' ); $links = get_bookmarks( array( 'category' => $category, 'orderby' => $orderby, 'limit' => $limit ) ) ; $links_array = array(); foreach ($links as $link) $links_array[] = $link; return $links_array; } /** * Gets the links associated with category 'cat_name' and display rating stars/chars. * * @since 0.71 * @deprecated 2.1.0 Use get_bookmarks() * @see get_bookmarks() * * @param string $cat_name The category name to use. If no match is found uses all * @param string $before The html to output before the link * @param string $after The html to output after the link * @param string $between The html to output between the link/image and its description. Not used if no image or show_images is true * @param bool $show_images Whether to show images (if defined). * @param string $orderby the order to output the links. E.g. 'id', 'name', 'url', * 'description', or 'rating'. Or maybe owner. If you start the name with an * underscore the order will be reversed. You can also specify 'rand' as the * order which will return links in a random order. * @param bool $show_description Whether to show the description if show_images=false/not defined * @param int $limit Limit to X entries. If not specified, all entries are shown. * @param int $show_updated Whether to show last updated timestamp */ function get_linksbyname_withrating($cat_name = "noname", $before = '', $after = '
    ', $between = " ", $show_images = true, $orderby = 'id', $show_description = true, $limit = -1, $show_updated = 0) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmarks()' ); get_linksbyname($cat_name, $before, $after, $between, $show_images, $orderby, $show_description, true, $limit, $show_updated); } /** * Gets the links associated with category n and display rating stars/chars. * * @since 0.71 * @deprecated 2.1.0 Use get_bookmarks() * @see get_bookmarks() * * @param int $category The category to use. If no category supplied uses all * @param string $before The html to output before the link * @param string $after The html to output after the link * @param string $between The html to output between the link/image and its description. Not used if no image or show_images == true * @param bool $show_images Whether to show images (if defined). * @param string $orderby The order to output the links. E.g. 'id', 'name', 'url', * 'description', or 'rating'. Or maybe owner. If you start the name with an * underscore the order will be reversed. You can also specify 'rand' as the * order which will return links in a random order. * @param bool $show_description Whether to show the description if show_images=false/not defined. * @param int $limit Limit to X entries. If not specified, all entries are shown. * @param int $show_updated Whether to show last updated timestamp */ function get_links_withrating($category = -1, $before = '', $after = '
    ', $between = " ", $show_images = true, $orderby = 'id', $show_description = true, $limit = -1, $show_updated = 0) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmarks()' ); get_links($category, $before, $after, $between, $show_images, $orderby, $show_description, true, $limit, $show_updated); } /** * Gets the auto_toggle setting. * * @since 0.71 * @deprecated 2.1.0 * * @param int $id The category to get. If no category supplied uses 0 * @return int Only returns 0. */ function get_autotoggle($id = 0) { _deprecated_function( __FUNCTION__, '2.1.0' ); return 0; } /** * Lists categories. * * @since 0.71 * @deprecated 2.1.0 Use wp_list_categories() * @see wp_list_categories() * * @param int $optionall * @param string $all * @param string $sort_column * @param string $sort_order * @param string $file * @param bool $list * @param int $optiondates * @param int $optioncount * @param int $hide_empty * @param int $use_desc_for_title * @param bool $children * @param int $child_of * @param int $categories * @param int $recurse * @param string $feed * @param string $feed_image * @param string $exclude * @param bool $hierarchical * @return false|null */ function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_order = 'asc', $file = '', $list = true, $optiondates = 0, $optioncount = 0, $hide_empty = 1, $use_desc_for_title = 1, $children=false, $child_of=0, $categories=0, $recurse=0, $feed = '', $feed_image = '', $exclude = '', $hierarchical=false) { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_list_categories()' ); $query = compact('optionall', 'all', 'sort_column', 'sort_order', 'file', 'list', 'optiondates', 'optioncount', 'hide_empty', 'use_desc_for_title', 'children', 'child_of', 'categories', 'recurse', 'feed', 'feed_image', 'exclude', 'hierarchical'); return wp_list_cats($query); } /** * Lists categories. * * @since 1.2.0 * @deprecated 2.1.0 Use wp_list_categories() * @see wp_list_categories() * * @param string|array $args * @return false|null|string */ function wp_list_cats($args = '') { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_list_categories()' ); $r = wp_parse_args( $args ); // Map to new names. if ( isset($r['optionall']) && isset($r['all'])) $r['show_option_all'] = $r['all']; if ( isset($r['sort_column']) ) $r['orderby'] = $r['sort_column']; if ( isset($r['sort_order']) ) $r['order'] = $r['sort_order']; if ( isset($r['optiondates']) ) $r['show_last_update'] = $r['optiondates']; if ( isset($r['optioncount']) ) $r['show_count'] = $r['optioncount']; if ( isset($r['list']) ) $r['style'] = $r['list'] ? 'list' : 'break'; $r['title_li'] = ''; return wp_list_categories($r); } /** * Deprecated method for generating a drop-down of categories. * * @since 0.71 * @deprecated 2.1.0 Use wp_dropdown_categories() * @see wp_dropdown_categories() * * @param int $optionall * @param string $all * @param string $orderby * @param string $order * @param int $show_last_update * @param int $show_count * @param int $hide_empty * @param bool $optionnone * @param int $selected * @param int $exclude * @return string */ function dropdown_cats($optionall = 1, $all = 'All', $orderby = 'ID', $order = 'asc', $show_last_update = 0, $show_count = 0, $hide_empty = 1, $optionnone = false, $selected = 0, $exclude = 0) { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_dropdown_categories()' ); $show_option_all = ''; if ( $optionall ) $show_option_all = $all; $show_option_none = ''; if ( $optionnone ) $show_option_none = __('None'); $vars = compact('show_option_all', 'show_option_none', 'orderby', 'order', 'show_last_update', 'show_count', 'hide_empty', 'selected', 'exclude'); $query = add_query_arg($vars, ''); return wp_dropdown_categories($query); } /** * Lists authors. * * @since 1.2.0 * @deprecated 2.1.0 Use wp_list_authors() * @see wp_list_authors() * * @param bool $optioncount * @param bool $exclude_admin * @param bool $show_fullname * @param bool $hide_empty * @param string $feed * @param string $feed_image * @return null|string */ function list_authors($optioncount = false, $exclude_admin = true, $show_fullname = false, $hide_empty = true, $feed = '', $feed_image = '') { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_list_authors()' ); $args = compact('optioncount', 'exclude_admin', 'show_fullname', 'hide_empty', 'feed', 'feed_image'); return wp_list_authors($args); } /** * Retrieves a list of post categories. * * @since 1.0.1 * @deprecated 2.1.0 Use wp_get_post_categories() * @see wp_get_post_categories() * * @param int $blogid Not Used * @param int $post_ID * @return array */ function wp_get_post_cats($blogid = '1', $post_ID = 0) { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_get_post_categories()' ); return wp_get_post_categories($post_ID); } /** * Sets the categories that the post id belongs to. * * @since 1.0.1 * @deprecated 2.1.0 * @deprecated Use wp_set_post_categories() * @see wp_set_post_categories() * * @param int $blogid Not used * @param int $post_ID * @param array $post_categories * @return bool|mixed */ function wp_set_post_cats($blogid = '1', $post_ID = 0, $post_categories = array()) { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_set_post_categories()' ); return wp_set_post_categories($post_ID, $post_categories); } /** * Retrieves a list of archives. * * @since 0.71 * @deprecated 2.1.0 Use wp_get_archives() * @see wp_get_archives() * * @param string $type * @param string $limit * @param string $format * @param string $before * @param string $after * @param bool $show_post_count * @return string|null */ function get_archives($type='', $limit='', $format='html', $before = '', $after = '', $show_post_count = false) { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_get_archives()' ); $args = compact('type', 'limit', 'format', 'before', 'after', 'show_post_count'); return wp_get_archives($args); } /** * Returns or Prints link to the author's posts. * * @since 1.2.0 * @deprecated 2.1.0 Use get_author_posts_url() * @see get_author_posts_url() * * @param bool $echo * @param int $author_id * @param string $author_nicename Optional. * @return string|null */ function get_author_link($echo, $author_id, $author_nicename = '') { _deprecated_function( __FUNCTION__, '2.1.0', 'get_author_posts_url()' ); $link = get_author_posts_url($author_id, $author_nicename); if ( $echo ) echo $link; return $link; } /** * Print list of pages based on arguments. * * @since 0.71 * @deprecated 2.1.0 Use wp_link_pages() * @see wp_link_pages() * * @param string $before * @param string $after * @param string $next_or_number * @param string $nextpagelink * @param string $previouspagelink * @param string $pagelink * @param string $more_file * @return string */ function link_pages($before='
    ', $after='
    ', $next_or_number='number', $nextpagelink='next page', $previouspagelink='previous page', $pagelink='%', $more_file='') { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_link_pages()' ); $args = compact('before', 'after', 'next_or_number', 'nextpagelink', 'previouspagelink', 'pagelink', 'more_file'); return wp_link_pages($args); } /** * Get value based on option. * * @since 0.71 * @deprecated 2.1.0 Use get_option() * @see get_option() * * @param string $option * @return string */ function get_settings($option) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_option()' ); return get_option($option); } /** * Print the permalink of the current post in the loop. * * @since 0.71 * @deprecated 1.2.0 Use the_permalink() * @see the_permalink() */ function permalink_link() { _deprecated_function( __FUNCTION__, '1.2.0', 'the_permalink()' ); the_permalink(); } /** * Print the permalink to the RSS feed. * * @since 0.71 * @deprecated 2.3.0 Use the_permalink_rss() * @see the_permalink_rss() * * @param string $deprecated */ function permalink_single_rss($deprecated = '') { _deprecated_function( __FUNCTION__, '2.3.0', 'the_permalink_rss()' ); the_permalink_rss(); } /** * Gets the links associated with category. * * @since 1.0.1 * @deprecated 2.1.0 Use wp_list_bookmarks() * @see wp_list_bookmarks() * * @param string $args a query string * @return null|string */ function wp_get_links($args = '') { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_list_bookmarks()' ); if ( strpos( $args, '=' ) === false ) { $cat_id = $args; $args = add_query_arg( 'category', $cat_id, $args ); } $defaults = array( 'after' => '
    ', 'before' => '', 'between' => ' ', 'categorize' => 0, 'category' => '', 'echo' => true, 'limit' => -1, 'orderby' => 'name', 'show_description' => true, 'show_images' => true, 'show_rating' => false, 'show_updated' => true, 'title_li' => '', ); $r = wp_parse_args( $args, $defaults ); return wp_list_bookmarks($r); } /** * Gets the links associated with category by id. * * @since 0.71 * @deprecated 2.1.0 Use get_bookmarks() * @see get_bookmarks() * * @param int $category The category to use. If no category supplied uses all * @param string $before the html to output before the link * @param string $after the html to output after the link * @param string $between the html to output between the link/image and its description. * Not used if no image or show_images == true * @param bool $show_images whether to show images (if defined). * @param string $orderby the order to output the links. E.g. 'id', 'name', 'url', * 'description', or 'rating'. Or maybe owner. If you start the name with an * underscore the order will be reversed. You can also specify 'rand' as the order * which will return links in a random order. * @param bool $show_description whether to show the description if show_images=false/not defined. * @param bool $show_rating show rating stars/chars * @param int $limit Limit to X entries. If not specified, all entries are shown. * @param int $show_updated whether to show last updated timestamp * @param bool $echo whether to echo the results, or return them instead * @return null|string */ function get_links($category = -1, $before = '', $after = '
    ', $between = ' ', $show_images = true, $orderby = 'name', $show_description = true, $show_rating = false, $limit = -1, $show_updated = 1, $echo = true) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmarks()' ); $order = 'ASC'; if ( substr($orderby, 0, 1) == '_' ) { $order = 'DESC'; $orderby = substr($orderby, 1); } if ( $category == -1 ) //get_bookmarks uses '' to signify all categories $category = ''; $results = get_bookmarks(array('category' => $category, 'orderby' => $orderby, 'order' => $order, 'show_updated' => $show_updated, 'limit' => $limit)); if ( !$results ) return; $output = ''; foreach ( (array) $results as $row ) { if ( !isset($row->recently_updated) ) $row->recently_updated = false; $output .= $before; if ( $show_updated && $row->recently_updated ) $output .= get_option('links_recently_updated_prepend'); $the_link = '#'; if ( !empty($row->link_url) ) $the_link = esc_url($row->link_url); $rel = $row->link_rel; if ( '' != $rel ) $rel = ' rel="' . $rel . '"'; $desc = esc_attr(sanitize_bookmark_field('link_description', $row->link_description, $row->link_id, 'display')); $name = esc_attr(sanitize_bookmark_field('link_name', $row->link_name, $row->link_id, 'display')); $title = $desc; if ( $show_updated ) if (substr($row->link_updated_f, 0, 2) != '00') $title .= ' ('.__('Last updated') . ' ' . date(get_option('links_updated_date_format'), $row->link_updated_f + (get_option('gmt_offset') * HOUR_IN_SECONDS)) . ')'; if ( '' != $title ) $title = ' title="' . $title . '"'; $alt = ' alt="' . $name . '"'; $target = $row->link_target; if ( '' != $target ) $target = ' target="' . $target . '"'; $output .= ''; if ( $row->link_image != null && $show_images ) { if ( strpos($row->link_image, 'http') !== false ) $output .= "link_image\" $alt $title />"; else // If it's a relative path $output .= "link_image\" $alt $title />"; } else { $output .= $name; } $output .= ''; if ( $show_updated && $row->recently_updated ) $output .= get_option('links_recently_updated_append'); if ( $show_description && '' != $desc ) $output .= $between . $desc; if ($show_rating) { $output .= $between . get_linkrating($row); } $output .= "$after\n"; } // end while if ( !$echo ) return $output; echo $output; } /** * Output entire list of links by category. * * Output a list of all links, listed by category, using the settings in * $wpdb->linkcategories and output it as a nested HTML unordered list. * * @since 1.0.1 * @deprecated 2.1.0 Use wp_list_bookmarks() * @see wp_list_bookmarks() * * @param string $order Sort link categories by 'name' or 'id' */ function get_links_list($order = 'name') { _deprecated_function( __FUNCTION__, '2.1.0', 'wp_list_bookmarks()' ); $order = strtolower($order); // Handle link category sorting $direction = 'ASC'; if ( '_' == substr($order,0,1) ) { $direction = 'DESC'; $order = substr($order,1); } if ( !isset($direction) ) $direction = ''; $cats = get_categories(array('type' => 'link', 'orderby' => $order, 'order' => $direction, 'hierarchical' => 0)); // Display each category if ( $cats ) { foreach ( (array) $cats as $cat ) { // Handle each category. // Display the category name echo '
  • ' . apply_filters('link_category', $cat->name ) . "

    \n\t\n
  • \n"; } } } /** * Show the link to the links popup and the number of links. * * @since 0.71 * @deprecated 2.1.0 * * @param string $text the text of the link * @param int $width the width of the popup window * @param int $height the height of the popup window * @param string $file the page to open in the popup window * @param bool $count the number of links in the db */ function links_popup_script($text = 'Links', $width=400, $height=400, $file='links.all.php', $count = true) { _deprecated_function( __FUNCTION__, '2.1.0' ); } /** * Legacy function that retrieved the value of a link's link_rating field. * * @since 1.0.1 * @deprecated 2.1.0 Use sanitize_bookmark_field() * @see sanitize_bookmark_field() * * @param object $link Link object. * @return mixed Value of the 'link_rating' field, false otherwise. */ function get_linkrating( $link ) { _deprecated_function( __FUNCTION__, '2.1.0', 'sanitize_bookmark_field()' ); return sanitize_bookmark_field('link_rating', $link->link_rating, $link->link_id, 'display'); } /** * Gets the name of category by id. * * @since 0.71 * @deprecated 2.1.0 Use get_category() * @see get_category() * * @param int $id The category to get. If no category supplied uses 0 * @return string */ function get_linkcatname($id = 0) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_category()' ); $id = (int) $id; if ( empty($id) ) return ''; $cats = wp_get_link_cats($id); if ( empty($cats) || ! is_array($cats) ) return ''; $cat_id = (int) $cats[0]; // Take the first cat. $cat = get_category($cat_id); return $cat->name; } /** * Print RSS comment feed link. * * @since 1.0.1 * @deprecated 2.5.0 Use post_comments_feed_link() * @see post_comments_feed_link() * * @param string $link_text */ function comments_rss_link($link_text = 'Comments RSS') { _deprecated_function( __FUNCTION__, '2.5.0', 'post_comments_feed_link()' ); post_comments_feed_link($link_text); } /** * Print/Return link to category RSS2 feed. * * @since 1.2.0 * @deprecated 2.5.0 Use get_category_feed_link() * @see get_category_feed_link() * * @param bool $echo * @param int $cat_ID * @return string */ function get_category_rss_link($echo = false, $cat_ID = 1) { _deprecated_function( __FUNCTION__, '2.5.0', 'get_category_feed_link()' ); $link = get_category_feed_link($cat_ID, 'rss2'); if ( $echo ) echo $link; return $link; } /** * Print/Return link to author RSS feed. * * @since 1.2.0 * @deprecated 2.5.0 Use get_author_feed_link() * @see get_author_feed_link() * * @param bool $echo * @param int $author_id * @return string */ function get_author_rss_link($echo = false, $author_id = 1) { _deprecated_function( __FUNCTION__, '2.5.0', 'get_author_feed_link()' ); $link = get_author_feed_link($author_id); if ( $echo ) echo $link; return $link; } /** * Return link to the post RSS feed. * * @since 1.5.0 * @deprecated 2.2.0 Use get_post_comments_feed_link() * @see get_post_comments_feed_link() * * @return string */ function comments_rss() { _deprecated_function( __FUNCTION__, '2.2.0', 'get_post_comments_feed_link()' ); return esc_url( get_post_comments_feed_link() ); } /** * An alias of wp_create_user(). * * @since 2.0.0 * @deprecated 2.0.0 Use wp_create_user() * @see wp_create_user() * * @param string $username The user's username. * @param string $password The user's password. * @param string $email The user's email. * @return int The new user's ID. */ function create_user($username, $password, $email) { _deprecated_function( __FUNCTION__, '2.0.0', 'wp_create_user()' ); return wp_create_user($username, $password, $email); } /** * Unused function. * * @deprecated 2.5.0 */ function gzip_compression() { _deprecated_function( __FUNCTION__, '2.5.0' ); return false; } /** * Retrieve an array of comment data about comment $comment_ID. * * @since 0.71 * @deprecated 2.7.0 Use get_comment() * @see get_comment() * * @param int $comment_ID The ID of the comment * @param int $no_cache Whether to use the cache (cast to bool) * @param bool $include_unapproved Whether to include unapproved comments * @return array The comment data */ function get_commentdata( $comment_ID, $no_cache = 0, $include_unapproved = false ) { _deprecated_function( __FUNCTION__, '2.7.0', 'get_comment()' ); return get_comment($comment_ID, ARRAY_A); } /** * Retrieve the category name by the category ID. * * @since 0.71 * @deprecated 2.8.0 Use get_cat_name() * @see get_cat_name() * * @param int $cat_ID Category ID * @return string category name */ function get_catname( $cat_ID ) { _deprecated_function( __FUNCTION__, '2.8.0', 'get_cat_name()' ); return get_cat_name( $cat_ID ); } /** * Retrieve category children list separated before and after the term IDs. * * @since 1.2.0 * @deprecated 2.8.0 Use get_term_children() * @see get_term_children() * * @param int $id Category ID to retrieve children. * @param string $before Optional. Prepend before category term ID. * @param string $after Optional, default is empty string. Append after category term ID. * @param array $visited Optional. Category Term IDs that have already been added. * @return string */ function get_category_children( $id, $before = '/', $after = '', $visited = array() ) { _deprecated_function( __FUNCTION__, '2.8.0', 'get_term_children()' ); if ( 0 == $id ) return ''; $chain = ''; /** TODO: consult hierarchy */ $cat_ids = get_all_category_ids(); foreach ( (array) $cat_ids as $cat_id ) { if ( $cat_id == $id ) continue; $category = get_category( $cat_id ); if ( is_wp_error( $category ) ) return $category; if ( $category->parent == $id && !in_array( $category->term_id, $visited ) ) { $visited[] = $category->term_id; $chain .= $before.$category->term_id.$after; $chain .= get_category_children( $category->term_id, $before, $after ); } } return $chain; } /** * Retrieves all category IDs. * * @since 2.0.0 * @deprecated 4.0.0 Use get_terms() * @see get_terms() * * @link https://codex.wordpress.org/Function_Reference/get_all_category_ids * * @return object List of all of the category IDs. */ function get_all_category_ids() { _deprecated_function( __FUNCTION__, '4.0.0', 'get_terms()' ); if ( ! $cat_ids = wp_cache_get( 'all_category_ids', 'category' ) ) { $cat_ids = get_terms( 'category', array('fields' => 'ids', 'get' => 'all') ); wp_cache_add( 'all_category_ids', $cat_ids, 'category' ); } return $cat_ids; } /** * Retrieve the description of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's description. */ function get_the_author_description() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'description\')' ); return get_the_author_meta('description'); } /** * Display the description of the author of the current post. * * @since 1.0.0 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_description() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'description\')' ); the_author_meta('description'); } /** * Retrieve the login name of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's login name (username). */ function get_the_author_login() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'login\')' ); return get_the_author_meta('login'); } /** * Display the login name of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_login() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'login\')' ); the_author_meta('login'); } /** * Retrieve the first name of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's first name. */ function get_the_author_firstname() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'first_name\')' ); return get_the_author_meta('first_name'); } /** * Display the first name of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_firstname() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'first_name\')' ); the_author_meta('first_name'); } /** * Retrieve the last name of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's last name. */ function get_the_author_lastname() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'last_name\')' ); return get_the_author_meta('last_name'); } /** * Display the last name of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_lastname() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'last_name\')' ); the_author_meta('last_name'); } /** * Retrieve the nickname of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's nickname. */ function get_the_author_nickname() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'nickname\')' ); return get_the_author_meta('nickname'); } /** * Display the nickname of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_nickname() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'nickname\')' ); the_author_meta('nickname'); } /** * Retrieve the email of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's username. */ function get_the_author_email() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'email\')' ); return get_the_author_meta('email'); } /** * Display the email of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_email() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'email\')' ); the_author_meta('email'); } /** * Retrieve the ICQ number of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's ICQ number. */ function get_the_author_icq() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'icq\')' ); return get_the_author_meta('icq'); } /** * Display the ICQ number of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_icq() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'icq\')' ); the_author_meta('icq'); } /** * Retrieve the Yahoo! IM name of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's Yahoo! IM name. */ function get_the_author_yim() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'yim\')' ); return get_the_author_meta('yim'); } /** * Display the Yahoo! IM name of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_yim() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'yim\')' ); the_author_meta('yim'); } /** * Retrieve the MSN address of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's MSN address. */ function get_the_author_msn() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'msn\')' ); return get_the_author_meta('msn'); } /** * Display the MSN address of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_msn() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'msn\')' ); the_author_meta('msn'); } /** * Retrieve the AIM address of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The author's AIM address. */ function get_the_author_aim() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'aim\')' ); return get_the_author_meta('aim'); } /** * Display the AIM address of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta('aim') * @see the_author_meta() */ function the_author_aim() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'aim\')' ); the_author_meta('aim'); } /** * Retrieve the specified author's preferred display name. * * @since 1.0.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @param int $auth_id The ID of the author. * @return string The author's display name. */ function get_author_name( $auth_id = false ) { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'display_name\')' ); return get_the_author_meta('display_name', $auth_id); } /** * Retrieve the URL to the home page of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string The URL to the author's page. */ function get_the_author_url() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'url\')' ); return get_the_author_meta('url'); } /** * Display the URL to the home page of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_url() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'url\')' ); the_author_meta('url'); } /** * Retrieve the ID of the author of the current post. * * @since 1.5.0 * @deprecated 2.8.0 Use get_the_author_meta() * @see get_the_author_meta() * * @return string|int The author's ID. */ function get_the_author_ID() { _deprecated_function( __FUNCTION__, '2.8.0', 'get_the_author_meta(\'ID\')' ); return get_the_author_meta('ID'); } /** * Display the ID of the author of the current post. * * @since 0.71 * @deprecated 2.8.0 Use the_author_meta() * @see the_author_meta() */ function the_author_ID() { _deprecated_function( __FUNCTION__, '2.8.0', 'the_author_meta(\'ID\')' ); the_author_meta('ID'); } /** * Display the post content for the feed. * * For encoding the html or the $encode_html parameter, there are three possible * values. '0' will make urls footnotes and use make_url_footnote(). '1' will * encode special characters and automatically display all of the content. The * value of '2' will strip all HTML tags from the content. * * Also note that you cannot set the amount of words and not set the html * encoding. If that is the case, then the html encoding will default to 2, * which will strip all HTML tags. * * To restrict the amount of words of the content, you can use the cut * parameter. If the content is less than the amount, then there won't be any * dots added to the end. If there is content left over, then dots will be added * and the rest of the content will be removed. * * @since 0.71 * * @deprecated 2.9.0 Use the_content_feed() * @see the_content_feed() * * @param string $more_link_text Optional. Text to display when more content is available but not displayed. * @param int $stripteaser Optional. Default is 0. * @param string $more_file Optional. * @param int $cut Optional. Amount of words to keep for the content. * @param int $encode_html Optional. How to encode the content. */ function the_content_rss($more_link_text='(more...)', $stripteaser=0, $more_file='', $cut = 0, $encode_html = 0) { _deprecated_function( __FUNCTION__, '2.9.0', 'the_content_feed' ); $content = get_the_content($more_link_text, $stripteaser); $content = apply_filters('the_content_rss', $content); if ( $cut && !$encode_html ) $encode_html = 2; if ( 1== $encode_html ) { $content = esc_html($content); $cut = 0; } elseif ( 0 == $encode_html ) { $content = make_url_footnote($content); } elseif ( 2 == $encode_html ) { $content = strip_tags($content); } if ( $cut ) { $blah = explode(' ', $content); if ( count($blah) > $cut ) { $k = $cut; $use_dotdotdot = 1; } else { $k = count($blah); $use_dotdotdot = 0; } /** @todo Check performance, might be faster to use array slice instead. */ for ( $i=0; $i<$k; $i++ ) $excerpt .= $blah[$i].' '; $excerpt .= ($use_dotdotdot) ? '...' : ''; $content = $excerpt; } $content = str_replace(']]>', ']]>', $content); echo $content; } /** * Strip HTML and put links at the bottom of stripped content. * * Searches for all of the links, strips them out of the content, and places * them at the bottom of the content with numbers. * * @since 0.71 * @deprecated 2.9.0 * * @param string $content Content to get links * @return string HTML stripped out of content with links at the bottom. */ function make_url_footnote( $content ) { _deprecated_function( __FUNCTION__, '2.9.0', '' ); preg_match_all( '/(.+?)<\/a>/', $content, $matches ); $links_summary = "\n"; for ( $i = 0, $c = count( $matches[0] ); $i < $c; $i++ ) { $link_match = $matches[0][$i]; $link_number = '['.($i+1).']'; $link_url = $matches[2][$i]; $link_text = $matches[4][$i]; $content = str_replace( $link_match, $link_text . ' ' . $link_number, $content ); $link_url = ( ( strtolower( substr( $link_url, 0, 7 ) ) != 'http://' ) && ( strtolower( substr( $link_url, 0, 8 ) ) != 'https://' ) ) ? get_option( 'home' ) . $link_url : $link_url; $links_summary .= "\n" . $link_number . ' ' . $link_url; } $content = strip_tags( $content ); $content .= $links_summary; return $content; } /** * Retrieve translated string with vertical bar context * * Quite a few times, there will be collisions with similar translatable text * found in more than two places but with different translated context. * * In order to use the separate contexts, the _c() function is used and the * translatable string uses a pipe ('|') which has the context the string is in. * * When the translated string is returned, it is everything before the pipe, not * including the pipe character. If there is no pipe in the translated text then * everything is returned. * * @since 2.2.0 * @deprecated 2.9.0 Use _x() * @see _x() * * @param string $text Text to translate * @param string $domain Optional. Domain to retrieve the translated text * @return string Translated context string without pipe */ function _c( $text, $domain = 'default' ) { _deprecated_function( __FUNCTION__, '2.9.0', '_x()' ); return before_last_bar( translate( $text, $domain ) ); } /** * Translates $text like translate(), but assumes that the text * contains a context after its last vertical bar. * * @since 2.5.0 * @deprecated 3.0.0 Use _x() * @see _x() * * @param string $text Text to translate * @param string $domain Domain to retrieve the translated text * @return string Translated text */ function translate_with_context( $text, $domain = 'default' ) { _deprecated_function( __FUNCTION__, '2.9.0', '_x()' ); return before_last_bar( translate( $text, $domain ) ); } /** * Legacy version of _n(), which supports contexts. * * Strips everything from the translation after the last bar. * * @since 2.7.0 * @deprecated 3.0.0 Use _nx() * @see _nx() * * @param string $single The text to be used if the number is singular. * @param string $plural The text to be used if the number is plural. * @param int $number The number to compare against to use either the singular or plural form. * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. * Default 'default'. * @return string The translated singular or plural form. */ function _nc( $single, $plural, $number, $domain = 'default' ) { _deprecated_function( __FUNCTION__, '2.9.0', '_nx()' ); return before_last_bar( _n( $single, $plural, $number, $domain ) ); } /** * Retrieve the plural or single form based on the amount. * * @since 1.2.0 * @deprecated 2.8.0 Use _n() * @see _n() */ function __ngettext() { _deprecated_function( __FUNCTION__, '2.8.0', '_n()' ); $args = func_get_args(); return call_user_func_array('_n', $args); } /** * Register plural strings in POT file, but don't translate them. * * @since 2.5.0 * @deprecated 2.8.0 Use _n_noop() * @see _n_noop() */ function __ngettext_noop() { _deprecated_function( __FUNCTION__, '2.8.0', '_n_noop()' ); $args = func_get_args(); return call_user_func_array('_n_noop', $args); } /** * Retrieve all autoload options, or all options if no autoloaded ones exist. * * @since 1.0.0 * @deprecated 3.0.0 Use wp_load_alloptions()) * @see wp_load_alloptions() * * @return array List of all options. */ function get_alloptions() { _deprecated_function( __FUNCTION__, '3.0.0', 'wp_load_alloptions()' ); return wp_load_alloptions(); } /** * Retrieve HTML content of attachment image with link. * * @since 2.0.0 * @deprecated 2.5.0 Use wp_get_attachment_link() * @see wp_get_attachment_link() * * @param int $id Optional. Post ID. * @param bool $fullsize Optional, default is false. Whether to use full size image. * @param array $max_dims Optional. Max image dimensions. * @param bool $permalink Optional, default is false. Whether to include permalink to image. * @return string */ function get_the_attachment_link($id = 0, $fullsize = false, $max_dims = false, $permalink = false) { _deprecated_function( __FUNCTION__, '2.5.0', 'wp_get_attachment_link()' ); $id = (int) $id; $_post = get_post($id); if ( ('attachment' != $_post->post_type) || !$url = wp_get_attachment_url($_post->ID) ) return __('Missing Attachment'); if ( $permalink ) $url = get_attachment_link($_post->ID); $post_title = esc_attr($_post->post_title); $innerHTML = get_attachment_innerHTML($_post->ID, $fullsize, $max_dims); return "$innerHTML"; } /** * Retrieve icon URL and Path. * * @since 2.1.0 * @deprecated 2.5.0 Use wp_get_attachment_image_src() * @see wp_get_attachment_image_src() * * @param int $id Optional. Post ID. * @param bool $fullsize Optional, default to false. Whether to have full image. * @return array Icon URL and full path to file, respectively. */ function get_attachment_icon_src( $id = 0, $fullsize = false ) { _deprecated_function( __FUNCTION__, '2.5.0', 'wp_get_attachment_image_src()' ); $id = (int) $id; if ( !$post = get_post($id) ) return false; $file = get_attached_file( $post->ID ); if ( !$fullsize && $src = wp_get_attachment_thumb_url( $post->ID ) ) { // We have a thumbnail desired, specified and existing $src_file = basename($src); } elseif ( wp_attachment_is_image( $post->ID ) ) { // We have an image without a thumbnail $src = wp_get_attachment_url( $post->ID ); $src_file = & $file; } elseif ( $src = wp_mime_type_icon( $post->ID ) ) { // No thumb, no image. We'll look for a mime-related icon instead. $icon_dir = apply_filters( 'icon_dir', get_template_directory() . '/images' ); $src_file = $icon_dir . '/' . basename($src); } if ( !isset($src) || !$src ) return false; return array($src, $src_file); } /** * Retrieve HTML content of icon attachment image element. * * @since 2.0.0 * @deprecated 2.5.0 Use wp_get_attachment_image() * @see wp_get_attachment_image() * * @param int $id Optional. Post ID. * @param bool $fullsize Optional, default to false. Whether to have full size image. * @param array $max_dims Optional. Dimensions of image. * @return false|string HTML content. */ function get_attachment_icon( $id = 0, $fullsize = false, $max_dims = false ) { _deprecated_function( __FUNCTION__, '2.5.0', 'wp_get_attachment_image()' ); $id = (int) $id; if ( !$post = get_post($id) ) return false; if ( !$src = get_attachment_icon_src( $post->ID, $fullsize ) ) return false; list($src, $src_file) = $src; // Do we need to constrain the image? if ( ($max_dims = apply_filters('attachment_max_dims', $max_dims)) && file_exists($src_file) ) { $imagesize = getimagesize($src_file); if (($imagesize[0] > $max_dims[0]) || $imagesize[1] > $max_dims[1] ) { $actual_aspect = $imagesize[0] / $imagesize[1]; $desired_aspect = $max_dims[0] / $max_dims[1]; if ( $actual_aspect >= $desired_aspect ) { $height = $actual_aspect * $max_dims[0]; $constraint = "width='{$max_dims[0]}' "; $post->iconsize = array($max_dims[0], $height); } else { $width = $max_dims[1] / $actual_aspect; $constraint = "height='{$max_dims[1]}' "; $post->iconsize = array($width, $max_dims[1]); } } else { $post->iconsize = array($imagesize[0], $imagesize[1]); $constraint = ''; } } else { $constraint = ''; } $post_title = esc_attr($post->post_title); $icon = "$post_title"; return apply_filters( 'attachment_icon', $icon, $post->ID ); } /** * Retrieve HTML content of image element. * * @since 2.0.0 * @deprecated 2.5.0 Use wp_get_attachment_image() * @see wp_get_attachment_image() * * @param int $id Optional. Post ID. * @param bool $fullsize Optional, default to false. Whether to have full size image. * @param array $max_dims Optional. Dimensions of image. * @return false|string */ function get_attachment_innerHTML($id = 0, $fullsize = false, $max_dims = false) { _deprecated_function( __FUNCTION__, '2.5.0', 'wp_get_attachment_image()' ); $id = (int) $id; if ( !$post = get_post($id) ) return false; if ( $innerHTML = get_attachment_icon($post->ID, $fullsize, $max_dims)) return $innerHTML; $innerHTML = esc_attr($post->post_title); return apply_filters('attachment_innerHTML', $innerHTML, $post->ID); } /** * Retrieves bookmark data based on ID. * * @since 2.0.0 * @deprecated 2.1.0 Use get_bookmark() * @see get_bookmark() * * @param int $bookmark_id ID of link * @param string $output Optional. Type of output. Accepts OBJECT, ARRAY_N, or ARRAY_A. * Default OBJECT. * @param string $filter Optional. How to filter the link for output. Accepts 'raw', 'edit', * 'attribute', 'js', 'db', or 'display'. Default 'raw'. * @return object|array Bookmark object or array, depending on the type specified by `$output`. */ function get_link( $bookmark_id, $output = OBJECT, $filter = 'raw' ) { _deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmark()' ); return get_bookmark($bookmark_id, $output, $filter); } /** * Performs esc_url() for database or redirect usage. * * @since 2.3.1 * @deprecated 2.8.0 Use esc_url_raw() * @see esc_url_raw() * * @param string $url The URL to be cleaned. * @param array $protocols An array of acceptable protocols. * @return string The cleaned URL. */ function sanitize_url( $url, $protocols = null ) { _deprecated_function( __FUNCTION__, '2.8.0', 'esc_url_raw()' ); return esc_url_raw( $url, $protocols ); } /** * Checks and cleans a URL. * * A number of characters are removed from the URL. If the URL is for displaying * (the default behaviour) ampersands are also replaced. The 'clean_url' filter * is applied to the returned cleaned URL. * * @since 1.2.0 * @deprecated 3.0.0 Use esc_url() * @see esc_url() * * @param string $url The URL to be cleaned. * @param array $protocols Optional. An array of acceptable protocols. * @param string $context Optional. How the URL will be used. Default is 'display'. * @return string The cleaned $url after the {@see 'clean_url'} filter is applied. */ function clean_url( $url, $protocols = null, $context = 'display' ) { if ( $context == 'db' ) _deprecated_function( 'clean_url( $context = \'db\' )', '3.0.0', 'esc_url_raw()' ); else _deprecated_function( __FUNCTION__, '3.0.0', 'esc_url()' ); return esc_url( $url, $protocols, $context ); } /** * Escape single quotes, specialchar double quotes, and fix line endings. * * The filter {@see 'js_escape'} is also applied by esc_js(). * * @since 2.0.4 * @deprecated 2.8.0 Use esc_js() * @see esc_js() * * @param string $text The text to be escaped. * @return string Escaped text. */ function js_escape( $text ) { _deprecated_function( __FUNCTION__, '2.8.0', 'esc_js()' ); return esc_js( $text ); } /** * Legacy escaping for HTML blocks. * * @deprecated 2.8.0 Use esc_html() * @see esc_html() * * @param string $string String to escape. * @param string $quote_style Unused. * @param false|string $charset Unused. * @param false $double_encode Whether to double encode. Unused. * @return string Escaped `$string`. */ function wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { _deprecated_function( __FUNCTION__, '2.8.0', 'esc_html()' ); if ( func_num_args() > 1 ) { // Maintain back-compat for people passing additional arguments. $args = func_get_args(); return call_user_func_array( '_wp_specialchars', $args ); } else { return esc_html( $string ); } } /** * Escaping for HTML attributes. * * @since 2.0.6 * @deprecated 2.8.0 Use esc_attr() * @see esc_attr() * * @param string $text * @return string */ function attribute_escape( $text ) { _deprecated_function( __FUNCTION__, '2.8.0', 'esc_attr()' ); return esc_attr( $text ); } /** * Register widget for sidebar with backward compatibility. * * Allows $name to be an array that accepts either three elements to grab the * first element and the third for the name or just uses the first element of * the array for the name. * * Passes to wp_register_sidebar_widget() after argument list and backward * compatibility is complete. * * @since 2.2.0 * @deprecated 2.8.0 Use wp_register_sidebar_widget() * @see wp_register_sidebar_widget() * * @param string|int $name Widget ID. * @param callable $output_callback Run when widget is called. * @param string $classname Optional. Classname widget option. Default empty. * @param mixed $params ,... Widget parameters. */ function register_sidebar_widget($name, $output_callback, $classname = '') { _deprecated_function( __FUNCTION__, '2.8.0', 'wp_register_sidebar_widget()' ); // Compat if ( is_array($name) ) { if ( count($name) == 3 ) $name = sprintf($name[0], $name[2]); else $name = $name[0]; } $id = sanitize_title($name); $options = array(); if ( !empty($classname) && is_string($classname) ) $options['classname'] = $classname; $params = array_slice(func_get_args(), 2); $args = array($id, $name, $output_callback, $options); if ( !empty($params) ) $args = array_merge($args, $params); call_user_func_array('wp_register_sidebar_widget', $args); } /** * Serves as an alias of wp_unregister_sidebar_widget(). * * @since 2.2.0 * @deprecated 2.8.0 Use wp_unregister_sidebar_widget() * @see wp_unregister_sidebar_widget() * * @param int|string $id Widget ID. */ function unregister_sidebar_widget($id) { _deprecated_function( __FUNCTION__, '2.8.0', 'wp_unregister_sidebar_widget()' ); return wp_unregister_sidebar_widget($id); } /** * Registers widget control callback for customizing options. * * Allows $name to be an array that accepts either three elements to grab the * first element and the third for the name or just uses the first element of * the array for the name. * * Passes to wp_register_widget_control() after the argument list has * been compiled. * * @since 2.2.0 * @deprecated 2.8.0 Use wp_register_widget_control() * @see wp_register_widget_control() * * @param int|string $name Sidebar ID. * @param callable $control_callback Widget control callback to display and process form. * @param int $width Widget width. * @param int $height Widget height. */ function register_widget_control($name, $control_callback, $width = '', $height = '') { _deprecated_function( __FUNCTION__, '2.8.0', 'wp_register_widget_control()' ); // Compat if ( is_array($name) ) { if ( count($name) == 3 ) $name = sprintf($name[0], $name[2]); else $name = $name[0]; } $id = sanitize_title($name); $options = array(); if ( !empty($width) ) $options['width'] = $width; if ( !empty($height) ) $options['height'] = $height; $params = array_slice(func_get_args(), 4); $args = array($id, $name, $control_callback, $options); if ( !empty($params) ) $args = array_merge($args, $params); call_user_func_array('wp_register_widget_control', $args); } /** * Alias of wp_unregister_widget_control(). * * @since 2.2.0 * @deprecated 2.8.0 Use wp_unregister_widget_control() * @see wp_unregister_widget_control() * * @param int|string $id Widget ID. */ function unregister_widget_control($id) { _deprecated_function( __FUNCTION__, '2.8.0', 'wp_unregister_widget_control()' ); return wp_unregister_widget_control($id); } /** * Remove user meta data. * * @since 2.0.0 * @deprecated 3.0.0 Use delete_user_meta() * @see delete_user_meta() * * @param int $user_id User ID. * @param string $meta_key Metadata key. * @param mixed $meta_value Metadata value. * @return bool True deletion completed and false if user_id is not a number. */ function delete_usermeta( $user_id, $meta_key, $meta_value = '' ) { _deprecated_function( __FUNCTION__, '3.0.0', 'delete_user_meta()' ); global $wpdb; if ( !is_numeric( $user_id ) ) return false; $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); if ( is_array($meta_value) || is_object($meta_value) ) $meta_value = serialize($meta_value); $meta_value = trim( $meta_value ); $cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); if ( $cur && $cur->umeta_id ) do_action( 'delete_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); if ( ! empty($meta_value) ) $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s AND meta_value = %s", $user_id, $meta_key, $meta_value) ); else $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); clean_user_cache( $user_id ); wp_cache_delete( $user_id, 'user_meta' ); if ( $cur && $cur->umeta_id ) do_action( 'deleted_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); return true; } /** * Retrieve user metadata. * * If $user_id is not a number, then the function will fail over with a 'false' * boolean return value. Other returned values depend on whether there is only * one item to be returned, which be that single item type. If there is more * than one metadata value, then it will be list of metadata values. * * @since 2.0.0 * @deprecated 3.0.0 Use get_user_meta() * @see get_user_meta() * * @param int $user_id User ID * @param string $meta_key Optional. Metadata key. * @return mixed */ function get_usermeta( $user_id, $meta_key = '' ) { _deprecated_function( __FUNCTION__, '3.0.0', 'get_user_meta()' ); global $wpdb; $user_id = (int) $user_id; if ( !$user_id ) return false; if ( !empty($meta_key) ) { $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); $user = wp_cache_get($user_id, 'users'); // Check the cached user object if ( false !== $user && isset($user->$meta_key) ) $metas = array($user->$meta_key); else $metas = $wpdb->get_col( $wpdb->prepare("SELECT meta_value FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); } else { $metas = $wpdb->get_col( $wpdb->prepare("SELECT meta_value FROM $wpdb->usermeta WHERE user_id = %d", $user_id) ); } if ( empty($metas) ) { if ( empty($meta_key) ) return array(); else return ''; } $metas = array_map('maybe_unserialize', $metas); if ( count($metas) == 1 ) return $metas[0]; else return $metas; } /** * Update metadata of user. * * There is no need to serialize values, they will be serialized if it is * needed. The metadata key can only be a string with underscores. All else will * be removed. * * Will remove the metadata, if the meta value is empty. * * @since 2.0.0 * @deprecated 3.0.0 Use update_user_meta() * @see update_user_meta() * * @param int $user_id User ID * @param string $meta_key Metadata key. * @param mixed $meta_value Metadata value. * @return bool True on successful update, false on failure. */ function update_usermeta( $user_id, $meta_key, $meta_value ) { _deprecated_function( __FUNCTION__, '3.0.0', 'update_user_meta()' ); global $wpdb; if ( !is_numeric( $user_id ) ) return false; $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); /** @todo Might need fix because usermeta data is assumed to be already escaped */ if ( is_string($meta_value) ) $meta_value = stripslashes($meta_value); $meta_value = maybe_serialize($meta_value); if (empty($meta_value)) { return delete_usermeta($user_id, $meta_key); } $cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); if ( $cur ) do_action( 'update_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); if ( !$cur ) $wpdb->insert($wpdb->usermeta, compact('user_id', 'meta_key', 'meta_value') ); elseif ( $cur->meta_value != $meta_value ) $wpdb->update($wpdb->usermeta, compact('meta_value'), compact('user_id', 'meta_key') ); else return false; clean_user_cache( $user_id ); wp_cache_delete( $user_id, 'user_meta' ); if ( !$cur ) do_action( 'added_usermeta', $wpdb->insert_id, $user_id, $meta_key, $meta_value ); else do_action( 'updated_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); return true; } /** * Get users for the site. * * For setups that use the multisite feature. Can be used outside of the * multisite feature. * * @since 2.2.0 * @deprecated 3.1.0 Use get_users() * @see get_users() * * @global wpdb $wpdb WordPress database abstraction object. * * @param int $id Site ID. * @return array List of users that are part of that site ID */ function get_users_of_blog( $id = '' ) { _deprecated_function( __FUNCTION__, '3.1.0', 'get_users()' ); global $wpdb; if ( empty( $id ) ) { $id = get_current_blog_id(); } $blog_prefix = $wpdb->get_blog_prefix($id); $users = $wpdb->get_results( "SELECT user_id, user_id AS ID, user_login, display_name, user_email, meta_value FROM $wpdb->users, $wpdb->usermeta WHERE {$wpdb->users}.ID = {$wpdb->usermeta}.user_id AND meta_key = '{$blog_prefix}capabilities' ORDER BY {$wpdb->usermeta}.user_id" ); return $users; } /** * Enable/disable automatic general feed link outputting. * * @since 2.8.0 * @deprecated 3.0.0 Use add_theme_support() * @see add_theme_support() * * @param bool $add Optional, default is true. Add or remove links. Defaults to true. */ function automatic_feed_links( $add = true ) { _deprecated_function( __FUNCTION__, '3.0.0', "add_theme_support( 'automatic-feed-links' )" ); if ( $add ) add_theme_support( 'automatic-feed-links' ); else remove_action( 'wp_head', 'feed_links_extra', 3 ); // Just do this yourself in 3.0+ } /** * Retrieve user data based on field. * * @since 1.5.0 * @deprecated 3.0.0 Use get_the_author_meta() * @see get_the_author_meta() * * @param string $field User meta field. * @param false|int $user Optional. User ID to retrieve the field for. Default false (current user). * @return string The author's field from the current author's DB object. */ function get_profile( $field, $user = false ) { _deprecated_function( __FUNCTION__, '3.0.0', 'get_the_author_meta()' ); if ( $user ) { $user = get_user_by( 'login', $user ); $user = $user->ID; } return get_the_author_meta( $field, $user ); } /** * Retrieves the number of posts a user has written. * * @since 0.71 * @deprecated 3.0.0 Use count_user_posts() * @see count_user_posts() * * @param int $userid User to count posts for. * @return int Number of posts the given user has written. */ function get_usernumposts( $userid ) { _deprecated_function( __FUNCTION__, '3.0.0', 'count_user_posts()' ); return count_user_posts( $userid ); } /** * Callback used to change %uXXXX to &#YYY; syntax * * @since 2.8.0 * @access private * @deprecated 3.0.0 * * @param array $matches Single Match * @return string An HTML entity */ function funky_javascript_callback($matches) { return "&#".base_convert($matches[1],16,10).";"; } /** * Fixes JavaScript bugs in browsers. * * Converts unicode characters to HTML numbered entities. * * @since 1.5.0 * @deprecated 3.0.0 * * @global $is_macIE * @global $is_winIE * * @param string $text Text to be made safe. * @return string Fixed text. */ function funky_javascript_fix($text) { _deprecated_function( __FUNCTION__, '3.0.0' ); // Fixes for browsers' JavaScript bugs. global $is_macIE, $is_winIE; if ( $is_winIE || $is_macIE ) $text = preg_replace_callback("/\%u([0-9A-F]{4,4})/", "funky_javascript_callback", $text); return $text; } /** * Checks that the taxonomy name exists. * * @since 2.3.0 * @deprecated 3.0.0 Use taxonomy_exists() * @see taxonomy_exists() * * @param string $taxonomy Name of taxonomy object * @return bool Whether the taxonomy exists. */ function is_taxonomy( $taxonomy ) { _deprecated_function( __FUNCTION__, '3.0.0', 'taxonomy_exists()' ); return taxonomy_exists( $taxonomy ); } /** * Check if Term exists. * * @since 2.3.0 * @deprecated 3.0.0 Use term_exists() * @see term_exists() * * @param int|string $term The term to check * @param string $taxonomy The taxonomy name to use * @param int $parent ID of parent term under which to confine the exists search. * @return mixed Get the term id or Term Object, if exists. */ function is_term( $term, $taxonomy = '', $parent = 0 ) { _deprecated_function( __FUNCTION__, '3.0.0', 'term_exists()' ); return term_exists( $term, $taxonomy, $parent ); } /** * Is the current admin page generated by a plugin? * * Use global $plugin_page and/or get_plugin_page_hookname() hooks. * * @since 1.5.0 * @deprecated 3.1.0 * * @global $plugin_page * * @return bool */ function is_plugin_page() { _deprecated_function( __FUNCTION__, '3.1.0' ); global $plugin_page; if ( isset($plugin_page) ) return true; return false; } /** * Update the categories cache. * * This function does not appear to be used anymore or does not appear to be * needed. It might be a legacy function left over from when there was a need * for updating the category cache. * * @since 1.5.0 * @deprecated 3.1.0 * * @return bool Always return True */ function update_category_cache() { _deprecated_function( __FUNCTION__, '3.1.0' ); return true; } /** * Check for PHP timezone support * * @since 2.9.0 * @deprecated 3.2.0 * * @return bool */ function wp_timezone_supported() { _deprecated_function( __FUNCTION__, '3.2.0' ); return true; } /** * Displays an editor: TinyMCE, HTML, or both. * * @since 2.1.0 * @deprecated 3.3.0 Use wp_editor() * @see wp_editor() * * @param string $content Textarea content. * @param string $id Optional. HTML ID attribute value. Default 'content'. * @param string $prev_id Optional. Unused. * @param bool $media_buttons Optional. Whether to display media buttons. Default true. * @param int $tab_index Optional. Unused. * @param bool $extended Optional. Unused. */ function the_editor($content, $id = 'content', $prev_id = 'title', $media_buttons = true, $tab_index = 2, $extended = true) { _deprecated_function( __FUNCTION__, '3.3.0', 'wp_editor()' ); wp_editor( $content, $id, array( 'media_buttons' => $media_buttons ) ); } /** * Perform the query to get the $metavalues array(s) needed by _fill_user and _fill_many_users * * @since 3.0.0 * @deprecated 3.3.0 * * @param array $ids User ID numbers list. * @return array of arrays. The array is indexed by user_id, containing $metavalues object arrays. */ function get_user_metavalues($ids) { _deprecated_function( __FUNCTION__, '3.3.0' ); $objects = array(); $ids = array_map('intval', $ids); foreach ( $ids as $id ) $objects[$id] = array(); $metas = update_meta_cache('user', $ids); foreach ( $metas as $id => $meta ) { foreach ( $meta as $key => $metavalues ) { foreach ( $metavalues as $value ) { $objects[$id][] = (object)array( 'user_id' => $id, 'meta_key' => $key, 'meta_value' => $value); } } } return $objects; } /** * Sanitize every user field. * * If the context is 'raw', then the user object or array will get minimal santization of the int fields. * * @since 2.3.0 * @deprecated 3.3.0 * * @param object|array $user The User Object or Array * @param string $context Optional, default is 'display'. How to sanitize user fields. * @return object|array The now sanitized User Object or Array (will be the same type as $user) */ function sanitize_user_object($user, $context = 'display') { _deprecated_function( __FUNCTION__, '3.3.0' ); if ( is_object($user) ) { if ( !isset($user->ID) ) $user->ID = 0; if ( ! ( $user instanceof WP_User ) ) { $vars = get_object_vars($user); foreach ( array_keys($vars) as $field ) { if ( is_string($user->$field) || is_numeric($user->$field) ) $user->$field = sanitize_user_field($field, $user->$field, $user->ID, $context); } } $user->filter = $context; } else { if ( !isset($user['ID']) ) $user['ID'] = 0; foreach ( array_keys($user) as $field ) $user[$field] = sanitize_user_field($field, $user[$field], $user['ID'], $context); $user['filter'] = $context; } return $user; } /** * Get boundary post relational link. * * Can either be start or end post relational link. * * @since 2.8.0 * @deprecated 3.3.0 * * @param string $title Optional. Link title format. * @param bool $in_same_cat Optional. Whether link should be in a same category. * @param string $excluded_categories Optional. Excluded categories IDs. * @param bool $start Optional, default is true. Whether to display link to first or last post. * @return string */ function get_boundary_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '', $start = true) { _deprecated_function( __FUNCTION__, '3.3.0' ); $posts = get_boundary_post($in_same_cat, $excluded_categories, $start); // If there is no post stop. if ( empty($posts) ) return; // Even though we limited get_posts to return only 1 item it still returns an array of objects. $post = $posts[0]; if ( empty($post->post_title) ) $post->post_title = $start ? __('First Post') : __('Last Post'); $date = mysql2date(get_option('date_format'), $post->post_date); $title = str_replace('%title', $post->post_title, $title); $title = str_replace('%date', $date, $title); $title = apply_filters('the_title', $title, $post->ID); $link = $start ? "\n"; $boundary = $start ? 'start' : 'end'; return apply_filters( "{$boundary}_post_rel_link", $link ); } /** * Display relational link for the first post. * * @since 2.8.0 * @deprecated 3.3.0 * * @param string $title Optional. Link title format. * @param bool $in_same_cat Optional. Whether link should be in a same category. * @param string $excluded_categories Optional. Excluded categories IDs. */ function start_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') { _deprecated_function( __FUNCTION__, '3.3.0' ); echo get_boundary_post_rel_link($title, $in_same_cat, $excluded_categories, true); } /** * Get site index relational link. * * @since 2.8.0 * @deprecated 3.3.0 * * @return string */ function get_index_rel_link() { _deprecated_function( __FUNCTION__, '3.3.0' ); $link = "\n"; return apply_filters( "index_rel_link", $link ); } /** * Display relational link for the site index. * * @since 2.8.0 * @deprecated 3.3.0 */ function index_rel_link() { _deprecated_function( __FUNCTION__, '3.3.0' ); echo get_index_rel_link(); } /** * Get parent post relational link. * * @since 2.8.0 * @deprecated 3.3.0 * * @param string $title Optional. Link title format. Default '%title'. * @return string */ function get_parent_post_rel_link( $title = '%title' ) { _deprecated_function( __FUNCTION__, '3.3.0' ); if ( ! empty( $GLOBALS['post'] ) && ! empty( $GLOBALS['post']->post_parent ) ) $post = get_post($GLOBALS['post']->post_parent); if ( empty($post) ) return; $date = mysql2date(get_option('date_format'), $post->post_date); $title = str_replace('%title', $post->post_title, $title); $title = str_replace('%date', $date, $title); $title = apply_filters('the_title', $title, $post->ID); $link = "\n"; return apply_filters( "parent_post_rel_link", $link ); } /** * Display relational link for parent item * * @since 2.8.0 * @deprecated 3.3.0 * * @param string $title Optional. Link title format. Default '%title'. */ function parent_post_rel_link( $title = '%title' ) { _deprecated_function( __FUNCTION__, '3.3.0' ); echo get_parent_post_rel_link($title); } /** * Add the "Dashboard"/"Visit Site" menu. * * @since 3.2.0 * @deprecated 3.3.0 * * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance. */ function wp_admin_bar_dashboard_view_site_menu( $wp_admin_bar ) { _deprecated_function( __FUNCTION__, '3.3.0' ); $user_id = get_current_user_id(); if ( 0 != $user_id ) { if ( is_admin() ) $wp_admin_bar->add_menu( array( 'id' => 'view-site', 'title' => __( 'Visit Site' ), 'href' => home_url() ) ); elseif ( is_multisite() ) $wp_admin_bar->add_menu( array( 'id' => 'dashboard', 'title' => __( 'Dashboard' ), 'href' => get_dashboard_url( $user_id ) ) ); else $wp_admin_bar->add_menu( array( 'id' => 'dashboard', 'title' => __( 'Dashboard' ), 'href' => admin_url() ) ); } } /** * Checks if the current user belong to a given site. * * @since MU * @deprecated 3.3.0 Use is_user_member_of_blog() * @see is_user_member_of_blog() * * @param int $blog_id Site ID * @return bool True if the current users belong to $blog_id, false if not. */ function is_blog_user( $blog_id = 0 ) { _deprecated_function( __FUNCTION__, '3.3.0', 'is_user_member_of_blog()' ); return is_user_member_of_blog( get_current_user_id(), $blog_id ); } /** * Open the file handle for debugging. * * @since 0.71 * @deprecated 3.4.0 Use error_log() * @see error_log() * * @link https://secure.php.net/manual/en/function.error-log.php * * @param string $filename File name. * @param string $mode Type of access you required to the stream. * @return false Always false. */ function debug_fopen( $filename, $mode ) { _deprecated_function( __FUNCTION__, 'error_log()' ); return false; } /** * Write contents to the file used for debugging. * * @since 0.71 * @deprecated 3.4.0 Use error_log() * @see error_log() * * @link https://secure.php.net/manual/en/function.error-log.php * * @param mixed $fp Unused. * @param string $string Message to log. */ function debug_fwrite( $fp, $string ) { _deprecated_function( __FUNCTION__, 'error_log()' ); if ( ! empty( $GLOBALS['debug'] ) ) error_log( $string ); } /** * Close the debugging file handle. * * @since 0.71 * @deprecated 3.4.0 Use error_log() * @see error_log() * * @link https://secure.php.net/manual/en/function.error-log.php * * @param mixed $fp Unused. */ function debug_fclose( $fp ) { _deprecated_function( __FUNCTION__, 'error_log()' ); } /** * Retrieve list of themes with theme data in theme directory. * * The theme is broken, if it doesn't have a parent theme and is missing either * style.css and, or index.php. If the theme has a parent theme then it is * broken, if it is missing style.css; index.php is optional. * * @since 1.5.0 * @deprecated 3.4.0 Use wp_get_themes() * @see wp_get_themes() * * @return array Theme list with theme data. */ function get_themes() { _deprecated_function( __FUNCTION__, '3.4.0', 'wp_get_themes()' ); global $wp_themes; if ( isset( $wp_themes ) ) return $wp_themes; $themes = wp_get_themes(); $wp_themes = array(); foreach ( $themes as $theme ) { $name = $theme->get('Name'); if ( isset( $wp_themes[ $name ] ) ) $wp_themes[ $name . '/' . $theme->get_stylesheet() ] = $theme; else $wp_themes[ $name ] = $theme; } return $wp_themes; } /** * Retrieve theme data. * * @since 1.5.0 * @deprecated 3.4.0 Use wp_get_theme() * @see wp_get_theme() * * @param string $theme Theme name. * @return array|null Null, if theme name does not exist. Theme data, if exists. */ function get_theme( $theme ) { _deprecated_function( __FUNCTION__, '3.4.0', 'wp_get_theme( $stylesheet )' ); $themes = get_themes(); if ( is_array( $themes ) && array_key_exists( $theme, $themes ) ) return $themes[ $theme ]; return null; } /** * Retrieve current theme name. * * @since 1.5.0 * @deprecated 3.4.0 Use wp_get_theme() * @see wp_get_theme() * * @return string */ function get_current_theme() { _deprecated_function( __FUNCTION__, '3.4.0', 'wp_get_theme()' ); if ( $theme = get_option( 'current_theme' ) ) return $theme; return wp_get_theme()->get('Name'); } /** * Accepts matches array from preg_replace_callback in wpautop() or a string. * * Ensures that the contents of a `
    ...
    ` HTML block are not * converted into paragraphs or line-breaks. * * @since 1.2.0 * @deprecated 3.4.0 * * @param array|string $matches The array or string * @return string The pre block without paragraph/line-break conversion. */ function clean_pre($matches) { _deprecated_function( __FUNCTION__, '3.4.0' ); if ( is_array($matches) ) $text = $matches[1] . $matches[2] . ""; else $text = $matches; $text = str_replace(array('
    ', '
    ', '
    '), array('', '', ''), $text); $text = str_replace('

    ', "\n", $text); $text = str_replace('

    ', '', $text); return $text; } /** * Add callbacks for image header display. * * @since 2.1.0 * @deprecated 3.4.0 Use add_theme_support() * @see add_theme_support() * * @param callable $wp_head_callback Call on the {@see 'wp_head'} action. * @param callable $admin_head_callback Call on custom header administration screen. * @param callable $admin_preview_callback Output a custom header image div on the custom header administration screen. Optional. */ function add_custom_image_header( $wp_head_callback, $admin_head_callback, $admin_preview_callback = '' ) { _deprecated_function( __FUNCTION__, '3.4.0', 'add_theme_support( \'custom-header\', $args )' ); $args = array( 'wp-head-callback' => $wp_head_callback, 'admin-head-callback' => $admin_head_callback, ); if ( $admin_preview_callback ) $args['admin-preview-callback'] = $admin_preview_callback; return add_theme_support( 'custom-header', $args ); } /** * Remove image header support. * * @since 3.1.0 * @deprecated 3.4.0 Use remove_theme_support() * @see remove_theme_support() * * @return null|bool Whether support was removed. */ function remove_custom_image_header() { _deprecated_function( __FUNCTION__, '3.4.0', 'remove_theme_support( \'custom-header\' )' ); return remove_theme_support( 'custom-header' ); } /** * Add callbacks for background image display. * * @since 3.0.0 * @deprecated 3.4.0 Use add_theme_support() * @see add_theme_support() * * @param callable $wp_head_callback Call on the {@see 'wp_head'} action. * @param callable $admin_head_callback Call on custom background administration screen. * @param callable $admin_preview_callback Output a custom background image div on the custom background administration screen. Optional. */ function add_custom_background( $wp_head_callback = '', $admin_head_callback = '', $admin_preview_callback = '' ) { _deprecated_function( __FUNCTION__, '3.4.0', 'add_theme_support( \'custom-background\', $args )' ); $args = array(); if ( $wp_head_callback ) $args['wp-head-callback'] = $wp_head_callback; if ( $admin_head_callback ) $args['admin-head-callback'] = $admin_head_callback; if ( $admin_preview_callback ) $args['admin-preview-callback'] = $admin_preview_callback; return add_theme_support( 'custom-background', $args ); } /** * Remove custom background support. * * @since 3.1.0 * @deprecated 3.4.0 Use add_custom_background() * @see add_custom_background() * * @return null|bool Whether support was removed. */ function remove_custom_background() { _deprecated_function( __FUNCTION__, '3.4.0', 'remove_theme_support( \'custom-background\' )' ); return remove_theme_support( 'custom-background' ); } /** * Retrieve theme data from parsed theme file. * * @since 1.5.0 * @deprecated 3.4.0 Use wp_get_theme() * @see wp_get_theme() * * @param string $theme_file Theme file path. * @return array Theme data. */ function get_theme_data( $theme_file ) { _deprecated_function( __FUNCTION__, '3.4.0', 'wp_get_theme()' ); $theme = new WP_Theme( basename( dirname( $theme_file ) ), dirname( dirname( $theme_file ) ) ); $theme_data = array( 'Name' => $theme->get('Name'), 'URI' => $theme->display('ThemeURI', true, false), 'Description' => $theme->display('Description', true, false), 'Author' => $theme->display('Author', true, false), 'AuthorURI' => $theme->display('AuthorURI', true, false), 'Version' => $theme->get('Version'), 'Template' => $theme->get('Template'), 'Status' => $theme->get('Status'), 'Tags' => $theme->get('Tags'), 'Title' => $theme->get('Name'), 'AuthorName' => $theme->get('Author'), ); foreach ( apply_filters( 'extra_theme_headers', array() ) as $extra_header ) { if ( ! isset( $theme_data[ $extra_header ] ) ) $theme_data[ $extra_header ] = $theme->get( $extra_header ); } return $theme_data; } /** * Alias of update_post_cache(). * * @see update_post_cache() Posts and pages are the same, alias is intentional * * @since 1.5.1 * @deprecated 3.4.0 Use update_post_cache() * @see update_post_cache() * * @param array $pages list of page objects */ function update_page_cache( &$pages ) { _deprecated_function( __FUNCTION__, '3.4.0', 'update_post_cache()' ); update_post_cache( $pages ); } /** * Will clean the page in the cache. * * Clean (read: delete) page from cache that matches $id. Will also clean cache * associated with 'all_page_ids' and 'get_pages'. * * @since 2.0.0 * @deprecated 3.4.0 Use clean_post_cache * @see clean_post_cache() * * @param int $id Page ID to clean */ function clean_page_cache( $id ) { _deprecated_function( __FUNCTION__, '3.4.0', 'clean_post_cache()' ); clean_post_cache( $id ); } /** * Retrieve nonce action "Are you sure" message. * * Deprecated in 3.4.1 and 3.5.0. Backported to 3.3.3. * * @since 2.0.4 * @deprecated 3.4.1 Use wp_nonce_ays() * @see wp_nonce_ays() * * @param string $action Nonce action. * @return string Are you sure message. */ function wp_explain_nonce( $action ) { _deprecated_function( __FUNCTION__, '3.4.1', 'wp_nonce_ays()' ); return __( 'Are you sure you want to do this?' ); } /** * Display "sticky" CSS class, if a post is sticky. * * @since 2.7.0 * @deprecated 3.5.0 Use post_class() * @see post_class() * * @param int $post_id An optional post ID. */ function sticky_class( $post_id = null ) { _deprecated_function( __FUNCTION__, '3.5.0', 'post_class()' ); if ( is_sticky( $post_id ) ) echo ' sticky'; } /** * Retrieve post ancestors. * * This is no longer needed as WP_Post lazy-loads the ancestors * property with get_post_ancestors(). * * @since 2.3.4 * @deprecated 3.5.0 Use get_post_ancestors() * @see get_post_ancestors() * * @param WP_Post &$post Post object, passed by reference (unused). */ function _get_post_ancestors( &$post ) { _deprecated_function( __FUNCTION__, '3.5.0' ); } /** * Load an image from a string, if PHP supports it. * * @since 2.1.0 * @deprecated 3.5.0 Use wp_get_image_editor() * @see wp_get_image_editor() * * @param string $file Filename of the image to load. * @return resource The resulting image resource on success, Error string on failure. */ function wp_load_image( $file ) { _deprecated_function( __FUNCTION__, '3.5.0', 'wp_get_image_editor()' ); if ( is_numeric( $file ) ) $file = get_attached_file( $file ); if ( ! is_file( $file ) ) { /* translators: %s: file name */ return sprintf( __( 'File “%s” doesn’t exist?' ), $file ); } if ( ! function_exists('imagecreatefromstring') ) return __('The GD image library is not installed.'); // Set artificially high because GD uses uncompressed images in memory. wp_raise_memory_limit( 'image' ); $image = imagecreatefromstring( file_get_contents( $file ) ); if ( ! is_resource( $image ) ) { /* translators: %s: file name */ return sprintf( __( 'File “%s” is not an image.' ), $file ); } return $image; } /** * Scale down an image to fit a particular size and save a new copy of the image. * * The PNG transparency will be preserved using the function, as well as the * image type. If the file going in is PNG, then the resized image is going to * be PNG. The only supported image types are PNG, GIF, and JPEG. * * Some functionality requires API to exist, so some PHP version may lose out * support. This is not the fault of WordPress (where functionality is * downgraded, not actual defects), but of your PHP version. * * @since 2.5.0 * @deprecated 3.5.0 Use wp_get_image_editor() * @see wp_get_image_editor() * * @param string $file Image file path. * @param int $max_w Maximum width to resize to. * @param int $max_h Maximum height to resize to. * @param bool $crop Optional. Whether to crop image or resize. * @param string $suffix Optional. File suffix. * @param string $dest_path Optional. New image file path. * @param int $jpeg_quality Optional, default is 90. Image quality percentage. * @return mixed WP_Error on failure. String with new destination path. */ function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) { _deprecated_function( __FUNCTION__, '3.5.0', 'wp_get_image_editor()' ); $editor = wp_get_image_editor( $file ); if ( is_wp_error( $editor ) ) return $editor; $editor->set_quality( $jpeg_quality ); $resized = $editor->resize( $max_w, $max_h, $crop ); if ( is_wp_error( $resized ) ) return $resized; $dest_file = $editor->generate_filename( $suffix, $dest_path ); $saved = $editor->save( $dest_file ); if ( is_wp_error( $saved ) ) return $saved; return $dest_file; } /** * Retrieve a single post, based on post ID. * * Has categories in 'post_category' property or key. Has tags in 'tags_input' * property or key. * * @since 1.0.0 * @deprecated 3.5.0 Use get_post() * @see get_post() * * @param int $postid Post ID. * @param string $mode How to return result, either OBJECT, ARRAY_N, or ARRAY_A. * @return WP_Post|null Post object or array holding post contents and information */ function wp_get_single_post( $postid = 0, $mode = OBJECT ) { _deprecated_function( __FUNCTION__, '3.5.0', 'get_post()' ); return get_post( $postid, $mode ); } /** * Check that the user login name and password is correct. * * @since 0.71 * @deprecated 3.5.0 Use wp_authenticate() * @see wp_authenticate() * * @param string $user_login User name. * @param string $user_pass User password. * @return bool False if does not authenticate, true if username and password authenticates. */ function user_pass_ok($user_login, $user_pass) { _deprecated_function( __FUNCTION__, '3.5.0', 'wp_authenticate()' ); $user = wp_authenticate( $user_login, $user_pass ); if ( is_wp_error( $user ) ) return false; return true; } /** * Callback formerly fired on the save_post hook. No longer needed. * * @since 2.3.0 * @deprecated 3.5.0 */ function _save_post_hook() {} /** * Check if the installed version of GD supports particular image type * * @since 2.9.0 * @deprecated 3.5.0 Use wp_image_editor_supports() * @see wp_image_editor_supports() * * @param string $mime_type * @return bool */ function gd_edit_image_support($mime_type) { _deprecated_function( __FUNCTION__, '3.5.0', 'wp_image_editor_supports()' ); if ( function_exists('imagetypes') ) { switch( $mime_type ) { case 'image/jpeg': return (imagetypes() & IMG_JPG) != 0; case 'image/png': return (imagetypes() & IMG_PNG) != 0; case 'image/gif': return (imagetypes() & IMG_GIF) != 0; } } else { switch( $mime_type ) { case 'image/jpeg': return function_exists('imagecreatefromjpeg'); case 'image/png': return function_exists('imagecreatefrompng'); case 'image/gif': return function_exists('imagecreatefromgif'); } } return false; } /** * Converts an integer byte value to a shorthand byte value. * * @since 2.3.0 * @deprecated 3.6.0 Use size_format() * @see size_format() * * @param int $bytes An integer byte value. * @return string A shorthand byte value. */ function wp_convert_bytes_to_hr( $bytes ) { _deprecated_function( __FUNCTION__, '3.6.0', 'size_format()' ); $units = array( 0 => 'B', 1 => 'KB', 2 => 'MB', 3 => 'GB', 4 => 'TB' ); $log = log( $bytes, KB_IN_BYTES ); $power = (int) $log; $size = pow( KB_IN_BYTES, $log - $power ); if ( ! is_nan( $size ) && array_key_exists( $power, $units ) ) { $unit = $units[ $power ]; } else { $size = $bytes; $unit = $units[0]; } return $size . $unit; } /** * Formerly used internally to tidy up the search terms. * * @since 2.9.0 * @access private * @deprecated 3.7.0 * * @param string $t Search terms to "tidy", e.g. trim. * @return string Trimmed search terms. */ function _search_terms_tidy( $t ) { _deprecated_function( __FUNCTION__, '3.7.0' ); return trim( $t, "\"'\n\r " ); } /** * Determine if TinyMCE is available. * * Checks to see if the user has deleted the tinymce files to slim down * their WordPress install. * * @since 2.1.0 * @deprecated 3.9.0 * * @return bool Whether TinyMCE exists. */ function rich_edit_exists() { global $wp_rich_edit_exists; _deprecated_function( __FUNCTION__, '3.9.0' ); if ( ! isset( $wp_rich_edit_exists ) ) $wp_rich_edit_exists = file_exists( ABSPATH . WPINC . '/js/tinymce/tinymce.js' ); return $wp_rich_edit_exists; } /** * Old callback for tag link tooltips. * * @since 2.7.0 * @access private * @deprecated 3.9.0 * * @param int $count Number of topics. * @return int Number of topics. */ function default_topic_count_text( $count ) { return $count; } /** * Formerly used to escape strings before inserting into the DB. * * Has not performed this function for many, many years. Use wpdb::prepare() instead. * * @since 0.71 * @deprecated 3.9.0 * * @param string $content The text to format. * @return string The very same text. */ function format_to_post( $content ) { _deprecated_function( __FUNCTION__, '3.9.0' ); return $content; } /** * Formerly used to escape strings before searching the DB. It was poorly documented and never worked as described. * * @since 2.5.0 * @deprecated 4.0.0 Use wpdb::esc_like() * @see wpdb::esc_like() * * @param string $text The text to be escaped. * @return string text, safe for inclusion in LIKE query. */ function like_escape($text) { _deprecated_function( __FUNCTION__, '4.0.0', 'wpdb::esc_like()' ); return str_replace( array( "%", "_" ), array( "\\%", "\\_" ), $text ); } /** * Determines if the URL can be accessed over SSL. * * Determines if the URL can be accessed over SSL by using the WordPress HTTP API to access * the URL using https as the scheme. * * @since 2.5.0 * @deprecated 4.0.0 * * @param string $url The URL to test. * @return bool Whether SSL access is available. */ function url_is_accessable_via_ssl( $url ) { _deprecated_function( __FUNCTION__, '4.0.0' ); $response = wp_remote_get( set_url_scheme( $url, 'https' ) ); if ( !is_wp_error( $response ) ) { $status = wp_remote_retrieve_response_code( $response ); if ( 200 == $status || 401 == $status ) { return true; } } return false; } /** * Start preview theme output buffer. * * Will only perform task if the user has permissions and template and preview * query variables exist. * * @since 2.6.0 * @deprecated 4.3.0 */ function preview_theme() { _deprecated_function( __FUNCTION__, '4.3.0' ); } /** * Private function to modify the current template when previewing a theme * * @since 2.9.0 * @deprecated 4.3.0 * @access private * * @return string */ function _preview_theme_template_filter() { _deprecated_function( __FUNCTION__, '4.3.0' ); return ''; } /** * Private function to modify the current stylesheet when previewing a theme * * @since 2.9.0 * @deprecated 4.3.0 * @access private * * @return string */ function _preview_theme_stylesheet_filter() { _deprecated_function( __FUNCTION__, '4.3.0' ); return ''; } /** * Callback function for ob_start() to capture all links in the theme. * * @since 2.6.0 * @deprecated 4.3.0 * @access private * * @param string $content * @return string */ function preview_theme_ob_filter( $content ) { _deprecated_function( __FUNCTION__, '4.3.0' ); return $content; } /** * Manipulates preview theme links in order to control and maintain location. * * Callback function for preg_replace_callback() to accept and filter matches. * * @since 2.6.0 * @deprecated 4.3.0 * @access private * * @param array $matches * @return string */ function preview_theme_ob_filter_callback( $matches ) { _deprecated_function( __FUNCTION__, '4.3.0' ); return ''; } /** * Formats text for the rich text editor. * * The {@see 'richedit_pre'} filter is applied here. If $text is empty the filter will * be applied to an empty string. * * @since 2.0.0 * @deprecated 4.3.0 * * @param string $text The text to be formatted. * @return string The formatted text after filter is applied. */ function wp_richedit_pre($text) { _deprecated_function( __FUNCTION__, '4.3.0', 'format_for_editor()' ); if ( empty( $text ) ) { /** * Filters text returned for the rich text editor. * * This filter is first evaluated, and the value returned, if an empty string * is passed to wp_richedit_pre(). If an empty string is passed, it results * in a break tag and line feed. * * If a non-empty string is passed, the filter is evaluated on the wp_richedit_pre() * return after being formatted. * * @since 2.0.0 * @deprecated 4.3.0 * * @param string $output Text for the rich text editor. */ return apply_filters( 'richedit_pre', '' ); } $output = convert_chars($text); $output = wpautop($output); $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); /** This filter is documented in wp-includes/deprecated.php */ return apply_filters( 'richedit_pre', $output ); } /** * Formats text for the HTML editor. * * Unless $output is empty it will pass through htmlspecialchars before the * {@see 'htmledit_pre'} filter is applied. * * @since 2.5.0 * @deprecated 4.3.0 Use format_for_editor() * @see format_for_editor() * * @param string $output The text to be formatted. * @return string Formatted text after filter applied. */ function wp_htmledit_pre($output) { _deprecated_function( __FUNCTION__, '4.3.0', 'format_for_editor()' ); if ( !empty($output) ) $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > & /** * Filters the text before it is formatted for the HTML editor. * * @since 2.5.0 * @deprecated 4.3.0 * * @param string $output The HTML-formatted text. */ return apply_filters( 'htmledit_pre', $output ); } /** * Retrieve permalink from post ID. * * @since 1.0.0 * @deprecated 4.4.0 Use get_permalink() * @see get_permalink() * * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default is global $post. * @return string|false */ function post_permalink( $post_id = 0 ) { _deprecated_function( __FUNCTION__, '4.4.0', 'get_permalink()' ); return get_permalink( $post_id ); } /** * Perform a HTTP HEAD or GET request. * * If $file_path is a writable filename, this will do a GET request and write * the file to that path. * * @since 2.5.0 * @deprecated 4.4.0 Use WP_Http * @see WP_Http * * @param string $url URL to fetch. * @param string|bool $file_path Optional. File path to write request to. Default false. * @param int $red Optional. The number of Redirects followed, Upon 5 being hit, * returns false. Default 1. * @return bool|string False on failure and string of headers if HEAD request. */ function wp_get_http( $url, $file_path = false, $red = 1 ) { _deprecated_function( __FUNCTION__, '4.4.0', 'WP_Http' ); @set_time_limit( 60 ); if ( $red > 5 ) return false; $options = array(); $options['redirection'] = 5; if ( false == $file_path ) $options['method'] = 'HEAD'; else $options['method'] = 'GET'; $response = wp_safe_remote_request( $url, $options ); if ( is_wp_error( $response ) ) return false; $headers = wp_remote_retrieve_headers( $response ); $headers['response'] = wp_remote_retrieve_response_code( $response ); // WP_HTTP no longer follows redirects for HEAD requests. if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) { return wp_get_http( $headers['location'], $file_path, ++$red ); } if ( false == $file_path ) return $headers; // GET request - write it to the supplied filename $out_fp = fopen($file_path, 'w'); if ( !$out_fp ) return $headers; fwrite( $out_fp, wp_remote_retrieve_body( $response ) ); fclose($out_fp); clearstatcache(); return $headers; } /** * Whether SSL login should be forced. * * @since 2.6.0 * @deprecated 4.4.0 Use force_ssl_admin() * @see force_ssl_admin() * * @param string|bool $force Optional Whether to force SSL login. Default null. * @return bool True if forced, false if not forced. */ function force_ssl_login( $force = null ) { _deprecated_function( __FUNCTION__, '4.4.0', 'force_ssl_admin()' ); return force_ssl_admin( $force ); } /** * Retrieve path of comment popup template in current or parent template. * * @since 1.5.0 * @deprecated 4.5.0 * * @return string Full path to comments popup template file. */ function get_comments_popup_template() { _deprecated_function( __FUNCTION__, '4.5.0' ); return ''; } /** * Whether the current URL is within the comments popup window. * * @since 1.5.0 * @deprecated 4.5.0 * * @return bool */ function is_comments_popup() { _deprecated_function( __FUNCTION__, '4.5.0' ); return false; } /** * Display the JS popup script to show a comment. * * @since 0.71 * @deprecated 4.5.0 */ function comments_popup_script() { _deprecated_function( __FUNCTION__, '4.5.0' ); } /** * Adds element attributes to open links in new windows. * * @since 0.71 * @deprecated 4.5.0 * * @param string $text Content to replace links to open in a new window. * @return string Content that has filtered links. */ function popuplinks( $text ) { _deprecated_function( __FUNCTION__, '4.5.0' ); $text = preg_replace('//i', "", $text); return $text; } /** * The Google Video embed handler callback. * * Deprecated function that previously assisted in turning Google Video URLs * into embeds but that service has since been shut down. * * @since 2.9.0 * @deprecated 4.6.0 * * @return string An empty string. */ function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) { _deprecated_function( __FUNCTION__, '4.6.0' ); return ''; } /** * Retrieve path of paged template in current or parent template. * * @since 1.5.0 * @deprecated 4.7.0 The paged.php template is no longer part of the theme template hierarchy. * * @return string Full path to paged template file. */ function get_paged_template() { _deprecated_function( __FUNCTION__, '4.7.0' ); return get_query_template( 'paged' ); } /** * Removes the HTML JavaScript entities found in early versions of Netscape 4. * * Previously, this function was pulled in from the original * import of kses and removed a specific vulnerability only * existent in early version of Netscape 4. However, this * vulnerability never affected any other browsers and can * be considered safe for the modern web. * * The regular expression which sanitized this vulnerability * has been removed in consideration of the performance and * energy demands it placed, now merely passing through its * input to the return. * * @since 1.0.0 * @deprecated deprecated since 4.7 * * @param string $string * @return string */ function wp_kses_js_entities( $string ) { _deprecated_function( __FUNCTION__, '4.7.0' ); return preg_replace( '%&\s*\{[^}]*(\}\s*;?|$)%', '', $string ); } /** * Sort categories by ID. * * Used by usort() as a callback, should not be used directly. Can actually be * used to sort any term object. * * @since 2.3.0 * @deprecated 4.7.0 Use wp_list_sort() * @access private * * @param object $a * @param object $b * @return int */ function _usort_terms_by_ID( $a, $b ) { _deprecated_function( __FUNCTION__, '4.7.0', 'wp_list_sort' ); if ( $a->term_id > $b->term_id ) return 1; elseif ( $a->term_id < $b->term_id ) return -1; else return 0; } /** * Sort categories by name. * * Used by usort() as a callback, should not be used directly. Can actually be * used to sort any term object. * * @since 2.3.0 * @deprecated 4.7.0 Use wp_list_sort() * @access private * * @param object $a * @param object $b * @return int */ function _usort_terms_by_name( $a, $b ) { _deprecated_function( __FUNCTION__, '4.7.0', 'wp_list_sort' ); return strcmp( $a->name, $b->name ); } /** * Sort menu items by the desired key. * * @since 3.0.0 * @deprecated 4.7.0 Use wp_list_sort() * @access private * * @global string $_menu_item_sort_prop * * @param object $a The first object to compare * @param object $b The second object to compare * @return int -1, 0, or 1 if $a is considered to be respectively less than, equal to, or greater than $b. */ function _sort_nav_menu_items( $a, $b ) { global $_menu_item_sort_prop; _deprecated_function( __FUNCTION__, '4.7.0', 'wp_list_sort' ); if ( empty( $_menu_item_sort_prop ) ) return 0; if ( ! isset( $a->$_menu_item_sort_prop ) || ! isset( $b->$_menu_item_sort_prop ) ) return 0; $_a = (int) $a->$_menu_item_sort_prop; $_b = (int) $b->$_menu_item_sort_prop; if ( $a->$_menu_item_sort_prop == $b->$_menu_item_sort_prop ) return 0; elseif ( $_a == $a->$_menu_item_sort_prop && $_b == $b->$_menu_item_sort_prop ) return $_a < $_b ? -1 : 1; else return strcmp( $a->$_menu_item_sort_prop, $b->$_menu_item_sort_prop ); } /** * Taxonomy API: WP_Tax_Query class * * @package WordPress * @subpackage Taxonomy * @since 4.4.0 */ /** * Core class used to implement taxonomy queries for the Taxonomy API. * * Used for generating SQL clauses that filter a primary query according to object * taxonomy terms. * * WP_Tax_Query is a helper that allows primary query classes, such as WP_Query, to filter * their results by object metadata, by generating `JOIN` and `WHERE` subclauses to be * attached to the primary SQL query string. * * @since 3.1.0 */ class WP_Tax_Query { /** * Array of taxonomy queries. * * See WP_Tax_Query::__construct() for information on tax query arguments. * * @since 3.1.0 * @access public * @var array */ public $queries = array(); /** * The relation between the queries. Can be one of 'AND' or 'OR'. * * @since 3.1.0 * @access public * @var string */ public $relation; /** * Standard response when the query should not return any rows. * * @since 3.2.0 * * @static * @access private * @var string */ private static $no_results = array( 'join' => array( '' ), 'where' => array( '0 = 1' ) ); /** * A flat list of table aliases used in the JOIN clauses. * * @since 4.1.0 * @access protected * @var array */ protected $table_aliases = array(); /** * Terms and taxonomies fetched by this query. * * We store this data in a flat array because they are referenced in a * number of places by WP_Query. * * @since 4.1.0 * @access public * @var array */ public $queried_terms = array(); /** * Database table that where the metadata's objects are stored (eg $wpdb->users). * * @since 4.1.0 * @access public * @var string */ public $primary_table; /** * Column in 'primary_table' that represents the ID of the object. * * @since 4.1.0 * @access public * @var string */ public $primary_id_column; /** * Constructor. * * @since 3.1.0 * @since 4.1.0 Added support for `$operator` 'NOT EXISTS' and 'EXISTS' values. * @access public * * @param array $tax_query { * Array of taxonomy query clauses. * * @type string $relation Optional. The MySQL keyword used to join * the clauses of the query. Accepts 'AND', or 'OR'. Default 'AND'. * @type array { * Optional. An array of first-order clause parameters, or another fully-formed tax query. * * @type string $taxonomy Taxonomy being queried. Optional when field=term_taxonomy_id. * @type string|int|array $terms Term or terms to filter by. * @type string $field Field to match $terms against. Accepts 'term_id', 'slug', * 'name', or 'term_taxonomy_id'. Default: 'term_id'. * @type string $operator MySQL operator to be used with $terms in the WHERE clause. * Accepts 'AND', 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS'. * Default: 'IN'. * @type bool $include_children Optional. Whether to include child terms. * Requires a $taxonomy. Default: true. * } * } */ public function __construct( $tax_query ) { if ( isset( $tax_query['relation'] ) ) { $this->relation = $this->sanitize_relation( $tax_query['relation'] ); } else { $this->relation = 'AND'; } $this->queries = $this->sanitize_query( $tax_query ); } /** * Ensure the 'tax_query' argument passed to the class constructor is well-formed. * * Ensures that each query-level clause has a 'relation' key, and that * each first-order clause contains all the necessary keys from `$defaults`. * * @since 4.1.0 * @access public * * @param array $queries Array of queries clauses. * @return array Sanitized array of query clauses. */ public function sanitize_query( $queries ) { $cleaned_query = array(); $defaults = array( 'taxonomy' => '', 'terms' => array(), 'field' => 'term_id', 'operator' => 'IN', 'include_children' => true, ); foreach ( $queries as $key => $query ) { if ( 'relation' === $key ) { $cleaned_query['relation'] = $this->sanitize_relation( $query ); // First-order clause. } elseif ( self::is_first_order_clause( $query ) ) { $cleaned_clause = array_merge( $defaults, $query ); $cleaned_clause['terms'] = (array) $cleaned_clause['terms']; $cleaned_query[] = $cleaned_clause; /* * Keep a copy of the clause in the flate * $queried_terms array, for use in WP_Query. */ if ( ! empty( $cleaned_clause['taxonomy'] ) && 'NOT IN' !== $cleaned_clause['operator'] ) { $taxonomy = $cleaned_clause['taxonomy']; if ( ! isset( $this->queried_terms[ $taxonomy ] ) ) { $this->queried_terms[ $taxonomy ] = array(); } /* * Backward compatibility: Only store the first * 'terms' and 'field' found for a given taxonomy. */ if ( ! empty( $cleaned_clause['terms'] ) && ! isset( $this->queried_terms[ $taxonomy ]['terms'] ) ) { $this->queried_terms[ $taxonomy ]['terms'] = $cleaned_clause['terms']; } if ( ! empty( $cleaned_clause['field'] ) && ! isset( $this->queried_terms[ $taxonomy ]['field'] ) ) { $this->queried_terms[ $taxonomy ]['field'] = $cleaned_clause['field']; } } // Otherwise, it's a nested query, so we recurse. } elseif ( is_array( $query ) ) { $cleaned_subquery = $this->sanitize_query( $query ); if ( ! empty( $cleaned_subquery ) ) { // All queries with children must have a relation. if ( ! isset( $cleaned_subquery['relation'] ) ) { $cleaned_subquery['relation'] = 'AND'; } $cleaned_query[] = $cleaned_subquery; } } } return $cleaned_query; } /** * Sanitize a 'relation' operator. * * @since 4.1.0 * @access public * * @param string $relation Raw relation key from the query argument. * @return string Sanitized relation ('AND' or 'OR'). */ public function sanitize_relation( $relation ) { if ( 'OR' === strtoupper( $relation ) ) { return 'OR'; } else { return 'AND'; } } /** * Determine whether a clause is first-order. * * A "first-order" clause is one that contains any of the first-order * clause keys ('terms', 'taxonomy', 'include_children', 'field', * 'operator'). An empty clause also counts as a first-order clause, * for backward compatibility. Any clause that doesn't meet this is * determined, by process of elimination, to be a higher-order query. * * @since 4.1.0 * * @static * @access protected * * @param array $query Tax query arguments. * @return bool Whether the query clause is a first-order clause. */ protected static function is_first_order_clause( $query ) { return is_array( $query ) && ( empty( $query ) || array_key_exists( 'terms', $query ) || array_key_exists( 'taxonomy', $query ) || array_key_exists( 'include_children', $query ) || array_key_exists( 'field', $query ) || array_key_exists( 'operator', $query ) ); } /** * Generates SQL clauses to be appended to a main query. * * @since 3.1.0 * * @static * @access public * * @param string $primary_table Database table where the object being filtered is stored (eg wp_users). * @param string $primary_id_column ID column for the filtered object in $primary_table. * @return array { * Array containing JOIN and WHERE SQL clauses to append to the main query. * * @type string $join SQL fragment to append to the main JOIN clause. * @type string $where SQL fragment to append to the main WHERE clause. * } */ public function get_sql( $primary_table, $primary_id_column ) { $this->primary_table = $primary_table; $this->primary_id_column = $primary_id_column; return $this->get_sql_clauses(); } /** * Generate SQL clauses to be appended to a main query. * * Called by the public WP_Tax_Query::get_sql(), this method * is abstracted out to maintain parity with the other Query classes. * * @since 4.1.0 * @access protected * * @return array { * Array containing JOIN and WHERE SQL clauses to append to the main query. * * @type string $join SQL fragment to append to the main JOIN clause. * @type string $where SQL fragment to append to the main WHERE clause. * } */ protected function get_sql_clauses() { /* * $queries are passed by reference to get_sql_for_query() for recursion. * To keep $this->queries unaltered, pass a copy. */ $queries = $this->queries; $sql = $this->get_sql_for_query( $queries ); if ( ! empty( $sql['where'] ) ) { $sql['where'] = ' AND ' . $sql['where']; } return $sql; } /** * Generate SQL clauses for a single query array. * * If nested subqueries are found, this method recurses the tree to * produce the properly nested SQL. * * @since 4.1.0 * @access protected * * @param array $query Query to parse, passed by reference. * @param int $depth Optional. Number of tree levels deep we currently are. * Used to calculate indentation. Default 0. * @return array { * Array containing JOIN and WHERE SQL clauses to append to a single query array. * * @type string $join SQL fragment to append to the main JOIN clause. * @type string $where SQL fragment to append to the main WHERE clause. * } */ protected function get_sql_for_query( &$query, $depth = 0 ) { $sql_chunks = array( 'join' => array(), 'where' => array(), ); $sql = array( 'join' => '', 'where' => '', ); $indent = ''; for ( $i = 0; $i < $depth; $i++ ) { $indent .= " "; } foreach ( $query as $key => &$clause ) { if ( 'relation' === $key ) { $relation = $query['relation']; } elseif ( is_array( $clause ) ) { // This is a first-order clause. if ( $this->is_first_order_clause( $clause ) ) { $clause_sql = $this->get_sql_for_clause( $clause, $query ); $where_count = count( $clause_sql['where'] ); if ( ! $where_count ) { $sql_chunks['where'][] = ''; } elseif ( 1 === $where_count ) { $sql_chunks['where'][] = $clause_sql['where'][0]; } else { $sql_chunks['where'][] = '( ' . implode( ' AND ', $clause_sql['where'] ) . ' )'; } $sql_chunks['join'] = array_merge( $sql_chunks['join'], $clause_sql['join'] ); // This is a subquery, so we recurse. } else { $clause_sql = $this->get_sql_for_query( $clause, $depth + 1 ); $sql_chunks['where'][] = $clause_sql['where']; $sql_chunks['join'][] = $clause_sql['join']; } } } // Filter to remove empties. $sql_chunks['join'] = array_filter( $sql_chunks['join'] ); $sql_chunks['where'] = array_filter( $sql_chunks['where'] ); if ( empty( $relation ) ) { $relation = 'AND'; } // Filter duplicate JOIN clauses and combine into a single string. if ( ! empty( $sql_chunks['join'] ) ) { $sql['join'] = implode( ' ', array_unique( $sql_chunks['join'] ) ); } // Generate a single WHERE clause with proper brackets and indentation. if ( ! empty( $sql_chunks['where'] ) ) { $sql['where'] = '( ' . "\n " . $indent . implode( ' ' . "\n " . $indent . $relation . ' ' . "\n " . $indent, $sql_chunks['where'] ) . "\n" . $indent . ')'; } return $sql; } /** * Generate SQL JOIN and WHERE clauses for a "first-order" query clause. * * @since 4.1.0 * @access public * * @global wpdb $wpdb The WordPress database abstraction object. * * @param array $clause Query clause, passed by reference. * @param array $parent_query Parent query array. * @return array { * Array containing JOIN and WHERE SQL clauses to append to a first-order query. * * @type string $join SQL fragment to append to the main JOIN clause. * @type string $where SQL fragment to append to the main WHERE clause. * } */ public function get_sql_for_clause( &$clause, $parent_query ) { global $wpdb; $sql = array( 'where' => array(), 'join' => array(), ); $join = $where = ''; $this->clean_query( $clause ); if ( is_wp_error( $clause ) ) { return self::$no_results; } $terms = $clause['terms']; $operator = strtoupper( $clause['operator'] ); if ( 'IN' == $operator ) { if ( empty( $terms ) ) { return self::$no_results; } $terms = implode( ',', $terms ); /* * Before creating another table join, see if this clause has a * sibling with an existing join that can be shared. */ $alias = $this->find_compatible_table_alias( $clause, $parent_query ); if ( false === $alias ) { $i = count( $this->table_aliases ); $alias = $i ? 'tt' . $i : $wpdb->term_relationships; // Store the alias as part of a flat array to build future iterators. $this->table_aliases[] = $alias; // Store the alias with this clause, so later siblings can use it. $clause['alias'] = $alias; $join .= " LEFT JOIN $wpdb->term_relationships"; $join .= $i ? " AS $alias" : ''; $join .= " ON ($this->primary_table.$this->primary_id_column = $alias.object_id)"; } $where = "$alias.term_taxonomy_id $operator ($terms)"; } elseif ( 'NOT IN' == $operator ) { if ( empty( $terms ) ) { return $sql; } $terms = implode( ',', $terms ); $where = "$this->primary_table.$this->primary_id_column NOT IN ( SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id IN ($terms) )"; } elseif ( 'AND' == $operator ) { if ( empty( $terms ) ) { return $sql; } $num_terms = count( $terms ); $terms = implode( ',', $terms ); $where = "( SELECT COUNT(1) FROM $wpdb->term_relationships WHERE term_taxonomy_id IN ($terms) AND object_id = $this->primary_table.$this->primary_id_column ) = $num_terms"; } elseif ( 'NOT EXISTS' === $operator || 'EXISTS' === $operator ) { $where = $wpdb->prepare( "$operator ( SELECT 1 FROM $wpdb->term_relationships INNER JOIN $wpdb->term_taxonomy ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id WHERE $wpdb->term_taxonomy.taxonomy = %s AND $wpdb->term_relationships.object_id = $this->primary_table.$this->primary_id_column )", $clause['taxonomy'] ); } $sql['join'][] = $join; $sql['where'][] = $where; return $sql; } /** * Identify an existing table alias that is compatible with the current query clause. * * We avoid unnecessary table joins by allowing each clause to look for * an existing table alias that is compatible with the query that it * needs to perform. * * An existing alias is compatible if (a) it is a sibling of `$clause` * (ie, it's under the scope of the same relation), and (b) the combination * of operator and relation between the clauses allows for a shared table * join. In the case of WP_Tax_Query, this only applies to 'IN' * clauses that are connected by the relation 'OR'. * * @since 4.1.0 * @access protected * * @param array $clause Query clause. * @param array $parent_query Parent query of $clause. * @return string|false Table alias if found, otherwise false. */ protected function find_compatible_table_alias( $clause, $parent_query ) { $alias = false; // Sanity check. Only IN queries use the JOIN syntax . if ( ! isset( $clause['operator'] ) || 'IN' !== $clause['operator'] ) { return $alias; } // Since we're only checking IN queries, we're only concerned with OR relations. if ( ! isset( $parent_query['relation'] ) || 'OR' !== $parent_query['relation'] ) { return $alias; } $compatible_operators = array( 'IN' ); foreach ( $parent_query as $sibling ) { if ( ! is_array( $sibling ) || ! $this->is_first_order_clause( $sibling ) ) { continue; } if ( empty( $sibling['alias'] ) || empty( $sibling['operator'] ) ) { continue; } // The sibling must both have compatible operator to share its alias. if ( in_array( strtoupper( $sibling['operator'] ), $compatible_operators ) ) { $alias = $sibling['alias']; break; } } return $alias; } /** * Validates a single query. * * @since 3.2.0 * @access private * * @param array $query The single query. Passed by reference. */ private function clean_query( &$query ) { if ( empty( $query['taxonomy'] ) ) { if ( 'term_taxonomy_id' !== $query['field'] ) { $query = new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) ); return; } // so long as there are shared terms, include_children requires that a taxonomy is set $query['include_children'] = false; } elseif ( ! taxonomy_exists( $query['taxonomy'] ) ) { $query = new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) ); return; } $query['terms'] = array_unique( (array) $query['terms'] ); if ( is_taxonomy_hierarchical( $query['taxonomy'] ) && $query['include_children'] ) { $this->transform_query( $query, 'term_id' ); if ( is_wp_error( $query ) ) return; $children = array(); foreach ( $query['terms'] as $term ) { $children = array_merge( $children, get_term_children( $term, $query['taxonomy'] ) ); $children[] = $term; } $query['terms'] = $children; } $this->transform_query( $query, 'term_taxonomy_id' ); } /** * Transforms a single query, from one field to another. * * @since 3.2.0 * * @global wpdb $wpdb The WordPress database abstraction object. * * @param array $query The single query. Passed by reference. * @param string $resulting_field The resulting field. Accepts 'slug', 'name', 'term_taxonomy_id', * or 'term_id'. Default 'term_id'. */ public function transform_query( &$query, $resulting_field ) { global $wpdb; if ( empty( $query['terms'] ) ) return; if ( $query['field'] == $resulting_field ) return; $resulting_field = sanitize_key( $resulting_field ); switch ( $query['field'] ) { case 'slug': case 'name': foreach ( $query['terms'] as &$term ) { /* * 0 is the $term_id parameter. We don't have a term ID yet, but it doesn't * matter because `sanitize_term_field()` ignores the $term_id param when the * context is 'db'. */ $term = "'" . esc_sql( sanitize_term_field( $query['field'], $term, 0, $query['taxonomy'], 'db' ) ) . "'"; } $terms = implode( ",", $query['terms'] ); $terms = $wpdb->get_col( " SELECT $wpdb->term_taxonomy.$resulting_field FROM $wpdb->term_taxonomy INNER JOIN $wpdb->terms USING (term_id) WHERE taxonomy = '{$query['taxonomy']}' AND $wpdb->terms.{$query['field']} IN ($terms) " ); break; case 'term_taxonomy_id': $terms = implode( ',', array_map( 'intval', $query['terms'] ) ); $terms = $wpdb->get_col( " SELECT $resulting_field FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ($terms) " ); break; default: $terms = implode( ',', array_map( 'intval', $query['terms'] ) ); $terms = $wpdb->get_col( " SELECT $resulting_field FROM $wpdb->term_taxonomy WHERE taxonomy = '{$query['taxonomy']}' AND term_id IN ($terms) " ); } if ( 'AND' == $query['operator'] && count( $terms ) < count( $query['terms'] ) ) { $query = new WP_Error( 'inexistent_terms', __( 'Inexistent terms.' ) ); return; } $query['terms'] = $terms; $query['field'] = $resulting_field; } } /** * API for fetching the HTML to embed remote content based on a provided URL * * Used internally by the WP_Embed class, but is designed to be generic. * * @link https://codex.wordpress.org/oEmbed oEmbed Codex Article * @link http://oembed.com/ oEmbed Homepage * * @package WordPress * @subpackage oEmbed */ /** * Core class used to implement oEmbed functionality. * * @since 2.9.0 */ class WP_oEmbed { /** * A list of oEmbed providers. * * @since 2.9.0 * @access public * @var array */ public $providers = array(); /** * A list of an early oEmbed providers. * * @since 4.0.0 * @access public * @static * @var array */ public static $early_providers = array(); /** * A list of private/protected methods, used for backward compatibility. * * @since 4.2.0 * @access private * @var array */ private $compat_methods = array( '_fetch_with_format', '_parse_json', '_parse_xml', '_parse_body' ); /** * Constructor. * * @since 2.9.0 * @access public */ public function __construct() { $host = urlencode( home_url() ); $providers = array( '#https?://((m|www)\.)?youtube\.com/watch.*#i' => array( 'https://www.youtube.com/oembed', true ), '#https?://((m|www)\.)?youtube\.com/playlist.*#i' => array( 'https://www.youtube.com/oembed', true ), '#https?://youtu\.be/.*#i' => array( 'https://www.youtube.com/oembed', true ), '#https?://(.+\.)?vimeo\.com/.*#i' => array( 'https://vimeo.com/api/oembed.{format}', true ), '#https?://(www\.)?dailymotion\.com/.*#i' => array( 'https://www.dailymotion.com/services/oembed', true ), '#https?://dai\.ly/.*#i' => array( 'https://www.dailymotion.com/services/oembed', true ), '#https?://(www\.)?flickr\.com/.*#i' => array( 'https://www.flickr.com/services/oembed/', true ), '#https?://flic\.kr/.*#i' => array( 'https://www.flickr.com/services/oembed/', true ), '#https?://(.+\.)?smugmug\.com/.*#i' => array( 'https://api.smugmug.com/services/oembed/', true ), '#https?://(www\.)?hulu\.com/watch/.*#i' => array( 'http://www.hulu.com/api/oembed.{format}', true ), 'http://i*.photobucket.com/albums/*' => array( 'http://api.photobucket.com/oembed', false ), 'http://gi*.photobucket.com/groups/*' => array( 'http://api.photobucket.com/oembed', false ), '#https?://(www\.)?scribd\.com/doc/.*#i' => array( 'https://www.scribd.com/services/oembed', true ), '#https?://wordpress\.tv/.*#i' => array( 'https://wordpress.tv/oembed/', true ), '#https?://(.+\.)?polldaddy\.com/.*#i' => array( 'https://polldaddy.com/oembed/', true ), '#https?://poll\.fm/.*#i' => array( 'https://polldaddy.com/oembed/', true ), '#https?://(www\.)?funnyordie\.com/videos/.*#i' => array( 'http://www.funnyordie.com/oembed', true ), '#https?://(www\.)?twitter\.com/\w{1,15}/status(es)?/.*#i' => array( 'https://publish.twitter.com/oembed', true ), '#https?://(www\.)?twitter\.com/\w{1,15}$#i' => array( 'https://publish.twitter.com/oembed', true ), '#https?://(www\.)?twitter\.com/\w{1,15}/likes$#i' => array( 'https://publish.twitter.com/oembed', true ), '#https?://(www\.)?twitter\.com/\w{1,15}/lists/.*#i' => array( 'https://publish.twitter.com/oembed', true ), '#https?://(www\.)?twitter\.com/\w{1,15}/timelines/.*#i' => array( 'https://publish.twitter.com/oembed', true ), '#https?://(www\.)?twitter\.com/i/moments/.*#i' => array( 'https://publish.twitter.com/oembed', true ), '#https?://vine\.co/v/.*#i' => array( 'https://vine.co/oembed.{format}', true ), '#https?://(www\.)?soundcloud\.com/.*#i' => array( 'https://soundcloud.com/oembed', true ), '#https?://(.+?\.)?slideshare\.net/.*#i' => array( 'https://www.slideshare.net/api/oembed/2', true ), '#https?://(www\.)?instagr(\.am|am\.com)/p/.*#i' => array( 'https://api.instagram.com/oembed', true ), '#https?://(open|play)\.spotify\.com/.*#i' => array( 'https://embed.spotify.com/oembed/', true ), '#https?://(.+\.)?imgur\.com/.*#i' => array( 'http://api.imgur.com/oembed', true ), '#https?://(www\.)?meetu(\.ps|p\.com)/.*#i' => array( 'https://api.meetup.com/oembed', true ), '#https?://(www\.)?issuu\.com/.+/docs/.+#i' => array( 'https://issuu.com/oembed_wp', true ), '#https?://(www\.)?collegehumor\.com/video/.*#i' => array( 'http://www.collegehumor.com/oembed.{format}', true ), '#https?://(www\.)?mixcloud\.com/.*#i' => array( 'https://www.mixcloud.com/oembed', true ), '#https?://(www\.|embed\.)?ted\.com/talks/.*#i' => array( 'https://www.ted.com/services/v1/oembed.{format}', true ), '#https?://(www\.)?(animoto|video214)\.com/play/.*#i' => array( 'https://animoto.com/oembeds/create', true ), '#https?://(.+)\.tumblr\.com/post/.*#i' => array( 'https://www.tumblr.com/oembed/1.0', true ), '#https?://(www\.)?kickstarter\.com/projects/.*#i' => array( 'https://www.kickstarter.com/services/oembed', true ), '#https?://kck\.st/.*#i' => array( 'https://www.kickstarter.com/services/oembed', true ), '#https?://cloudup\.com/.*#i' => array( 'https://cloudup.com/oembed', true ), '#https?://(www\.)?reverbnation\.com/.*#i' => array( 'https://www.reverbnation.com/oembed', true ), '#https?://videopress\.com/v/.*#' => array( 'https://public-api.wordpress.com/oembed/1.0/?for=' . $host, true ), '#https?://(www\.)?reddit\.com/r/[^/]+/comments/.*#i' => array( 'https://www.reddit.com/oembed', true ), '#https?://(www\.)?speakerdeck\.com/.*#i' => array( 'https://speakerdeck.com/oembed.{format}', true ), '#https?://www\.facebook\.com/.*/posts/.*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/.*/activity/.*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/.*/photos/.*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/photo(s/|\.php).*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/permalink\.php.*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/media/.*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/questions/.*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/notes/.*#i' => array( 'https://www.facebook.com/plugins/post/oembed.json/', true ), '#https?://www\.facebook\.com/.*/videos/.*#i' => array( 'https://www.facebook.com/plugins/video/oembed.json/', true ), '#https?://www\.facebook\.com/video\.php.*#i' => array( 'https://www.facebook.com/plugins/video/oembed.json/', true ), ); if ( ! empty( self::$early_providers['add'] ) ) { foreach ( self::$early_providers['add'] as $format => $data ) { $providers[ $format ] = $data; } } if ( ! empty( self::$early_providers['remove'] ) ) { foreach ( self::$early_providers['remove'] as $format ) { unset( $providers[ $format ] ); } } self::$early_providers = array(); /** * Filters the list of whitelisted oEmbed providers. * * Since WordPress 4.4, oEmbed discovery is enabled for all users and allows embedding of sanitized * iframes. The providers in this list are whitelisted, meaning they are trusted and allowed to * embed any content, such as iframes, videos, JavaScript, and arbitrary HTML. * * Supported providers: * * | Provider | Flavor | Supports HTTPS | Since | * | ------------ | --------------------- | :------------: | --------- | * | Dailymotion | dailymotion.com | Yes | 2.9.0 | * | Flickr | flickr.com | Yes | 2.9.0 | * | Hulu | hulu.com | Yes | 2.9.0 | * | Photobucket | photobucket.com | No | 2.9.0 | * | Scribd | scribd.com | Yes | 2.9.0 | * | Vimeo | vimeo.com | Yes | 2.9.0 | * | WordPress.tv | wordpress.tv | Yes | 2.9.0 | * | YouTube | youtube.com/watch | Yes | 2.9.0 | * | Funny or Die | funnyordie.com | Yes | 3.0.0 | * | Polldaddy | polldaddy.com | Yes | 3.0.0 | * | SmugMug | smugmug.com | Yes | 3.0.0 | * | YouTube | youtu.be | Yes | 3.0.0 | * | Twitter | twitter.com | Yes | 3.4.0 | * | Instagram | instagram.com | Yes | 3.5.0 | * | Instagram | instagr.am | Yes | 3.5.0 | * | Slideshare | slideshare.net | Yes | 3.5.0 | * | SoundCloud | soundcloud.com | Yes | 3.5.0 | * | Dailymotion | dai.ly | Yes | 3.6.0 | * | Flickr | flic.kr | Yes | 3.6.0 | * | Spotify | spotify.com | Yes | 3.6.0 | * | Imgur | imgur.com | Yes | 3.9.0 | * | Meetup.com | meetup.com | Yes | 3.9.0 | * | Meetup.com | meetu.ps | Yes | 3.9.0 | * | Animoto | animoto.com | Yes | 4.0.0 | * | Animoto | video214.com | Yes | 4.0.0 | * | CollegeHumor | collegehumor.com | Yes | 4.0.0 | * | Issuu | issuu.com | Yes | 4.0.0 | * | Mixcloud | mixcloud.com | Yes | 4.0.0 | * | Polldaddy | poll.fm | Yes | 4.0.0 | * | TED | ted.com | Yes | 4.0.0 | * | YouTube | youtube.com/playlist | Yes | 4.0.0 | * | Vine | vine.co | Yes | 4.1.0 | * | Tumblr | tumblr.com | Yes | 4.2.0 | * | Kickstarter | kickstarter.com | Yes | 4.2.0 | * | Kickstarter | kck.st | Yes | 4.2.0 | * | Cloudup | cloudup.com | Yes | 4.3.0 | * | ReverbNation | reverbnation.com | Yes | 4.4.0 | * | VideoPress | videopress.com | Yes | 4.4.0 | * | Reddit | reddit.com | Yes | 4.4.0 | * | Speaker Deck | speakerdeck.com | Yes | 4.4.0 | * | Twitter | twitter.com/timelines | Yes | 4.5.0 | * | Twitter | twitter.com/moments | Yes | 4.5.0 | * | Facebook | facebook.com | Yes | 4.7.0 | * | Twitter | twitter.com/user | Yes | 4.7.0 | * | Twitter | twitter.com/likes | Yes | 4.7.0 | * | Twitter | twitter.com/lists | Yes | 4.7.0 | * * No longer supported providers: * * | Provider | Flavor | Supports HTTPS | Since | Removed | * | ------------ | -------------------- | :------------: | --------- | --------- | * | Qik | qik.com | Yes | 2.9.0 | 3.9.0 | * | Viddler | viddler.com | Yes | 2.9.0 | 4.0.0 | * | Revision3 | revision3.com | No | 2.9.0 | 4.2.0 | * | Blip | blip.tv | No | 2.9.0 | 4.4.0 | * | Rdio | rdio.com | Yes | 3.6.0 | 4.4.1 | * | Rdio | rd.io | Yes | 3.6.0 | 4.4.1 | * * @see wp_oembed_add_provider() * * @since 2.9.0 * * @param array $providers An array of popular oEmbed providers. */ $this->providers = apply_filters( 'oembed_providers', $providers ); // Fix any embeds that contain new lines in the middle of the HTML which breaks wpautop(). add_filter( 'oembed_dataparse', array($this, '_strip_newlines'), 10, 3 ); } /** * Exposes private/protected methods for backward compatibility. * * @since 4.0.0 * @access public * * @param callable $name Method to call. * @param array $arguments Arguments to pass when calling. * @return mixed|bool Return value of the callback, false otherwise. */ public function __call( $name, $arguments ) { if ( in_array( $name, $this->compat_methods ) ) { return call_user_func_array( array( $this, $name ), $arguments ); } return false; } /** * Takes a URL and returns the corresponding oEmbed provider's URL, if there is one. * * @since 4.0.0 * @access public * * @see WP_oEmbed::discover() * * @param string $url The URL to the content. * @param string|array $args Optional provider arguments. * @return false|string False on failure, otherwise the oEmbed provider URL. */ public function get_provider( $url, $args = '' ) { $args = wp_parse_args( $args ); $provider = false; if ( !isset($args['discover']) ) $args['discover'] = true; foreach ( $this->providers as $matchmask => $data ) { list( $providerurl, $regex ) = $data; // Turn the asterisk-type provider URLs into regex if ( !$regex ) { $matchmask = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i'; $matchmask = preg_replace( '|^#http\\\://|', '#https?\://', $matchmask ); } if ( preg_match( $matchmask, $url ) ) { $provider = str_replace( '{format}', 'json', $providerurl ); // JSON is easier to deal with than XML break; } } if ( !$provider && $args['discover'] ) $provider = $this->discover( $url ); return $provider; } /** * Adds an oEmbed provider. * * The provider is added just-in-time when wp_oembed_add_provider() is called before * the {@see 'plugins_loaded'} hook. * * The just-in-time addition is for the benefit of the {@see 'oembed_providers'} filter. * * @static * @since 4.0.0 * @access public * * @see wp_oembed_add_provider() * * @param string $format Format of URL that this provider can handle. You can use * asterisks as wildcards. * @param string $provider The URL to the oEmbed provider.. * @param bool $regex Optional. Whether the $format parameter is in a regex format. * Default false. */ public static function _add_provider_early( $format, $provider, $regex = false ) { if ( empty( self::$early_providers['add'] ) ) { self::$early_providers['add'] = array(); } self::$early_providers['add'][ $format ] = array( $provider, $regex ); } /** * Removes an oEmbed provider. * * The provider is removed just-in-time when wp_oembed_remove_provider() is called before * the {@see 'plugins_loaded'} hook. * * The just-in-time removal is for the benefit of the {@see 'oembed_providers'} filter. * * @since 4.0.0 * @access public * @static * * @see wp_oembed_remove_provider() * * @param string $format The format of URL that this provider can handle. You can use * asterisks as wildcards. */ public static function _remove_provider_early( $format ) { if ( empty( self::$early_providers['remove'] ) ) { self::$early_providers['remove'] = array(); } self::$early_providers['remove'][] = $format; } /** * The do-it-all function that takes a URL and attempts to return the HTML. * * @see WP_oEmbed::fetch() * @see WP_oEmbed::data2html() * * @since 2.9.0 * @access public * * @param string $url The URL to the content that should be attempted to be embedded. * @param array|string $args Optional. Arguments, usually passed from a shortcode. Default empty. * @return false|string False on failure, otherwise the UNSANITIZED (and potentially unsafe) HTML that should be used to embed. */ public function get_html( $url, $args = '' ) { $args = wp_parse_args( $args ); /** * Filters the oEmbed result before any HTTP requests are made. * * This allows one to short-circuit the default logic, perhaps by * replacing it with a routine that is more optimal for your setup. * * Passing a non-null value to the filter will effectively short-circuit retrieval, * returning the passed value instead. * * @since 4.5.3 * * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. Default null. * @param string $url The URL to the content that should be attempted to be embedded. * @param array $args Optional. Arguments, usually passed from a shortcode. Default empty. */ $pre = apply_filters( 'pre_oembed_result', null, $url, $args ); if ( null !== $pre ) { return $pre; } $provider = $this->get_provider( $url, $args ); if ( ! $provider || false === $data = $this->fetch( $provider, $url, $args ) ) { return false; } /** * Filters the HTML returned by the oEmbed provider. * * @since 2.9.0 * * @param string $data The returned oEmbed HTML. * @param string $url URL of the content to be embedded. * @param array $args Optional arguments, usually passed from a shortcode. */ return apply_filters( 'oembed_result', $this->data2html( $data, $url ), $url, $args ); } /** * Attempts to discover link tags at the given URL for an oEmbed provider. * * @since 2.9.0 * @access public * * @param string $url The URL that should be inspected for discovery `` tags. * @return false|string False on failure, otherwise the oEmbed provider URL. */ public function discover( $url ) { $providers = array(); $args = array( 'limit_response_size' => 153600, // 150 KB ); /** * Filters oEmbed remote get arguments. * * @since 4.0.0 * * @see WP_Http::request() * * @param array $args oEmbed remote get arguments. * @param string $url URL to be inspected. */ $args = apply_filters( 'oembed_remote_get_args', $args, $url ); // Fetch URL content $request = wp_safe_remote_get( $url, $args ); if ( $html = wp_remote_retrieve_body( $request ) ) { /** * Filters the link types that contain oEmbed provider URLs. * * @since 2.9.0 * * @param array $format Array of oEmbed link types. Accepts 'application/json+oembed', * 'text/xml+oembed', and 'application/xml+oembed' (incorrect, * used by at least Vimeo). */ $linktypes = apply_filters( 'oembed_linktypes', array( 'application/json+oembed' => 'json', 'text/xml+oembed' => 'xml', 'application/xml+oembed' => 'xml', ) ); // Strip if ( $html_head_end = stripos( $html, '' ) ) { $html = substr( $html, 0, $html_head_end ); } // Do a quick check $tagfound = false; foreach ( $linktypes as $linktype => $format ) { if ( stripos($html, $linktype) ) { $tagfound = true; break; } } if ( $tagfound && preg_match_all( '#]+)/?>#iU', $html, $links ) ) { foreach ( $links[1] as $link ) { $atts = shortcode_parse_atts( $link ); if ( !empty($atts['type']) && !empty($linktypes[$atts['type']]) && !empty($atts['href']) ) { $providers[$linktypes[$atts['type']]] = htmlspecialchars_decode( $atts['href'] ); // Stop here if it's JSON (that's all we need) if ( 'json' == $linktypes[$atts['type']] ) break; } } } } // JSON is preferred to XML if ( !empty($providers['json']) ) return $providers['json']; elseif ( !empty($providers['xml']) ) return $providers['xml']; else return false; } /** * Connects to a oEmbed provider and returns the result. * * @since 2.9.0 * @access public * * @param string $provider The URL to the oEmbed provider. * @param string $url The URL to the content that is desired to be embedded. * @param array|string $args Optional. Arguments, usually passed from a shortcode. Default empty. * @return false|object False on failure, otherwise the result in the form of an object. */ public function fetch( $provider, $url, $args = '' ) { $args = wp_parse_args( $args, wp_embed_defaults( $url ) ); $provider = add_query_arg( 'maxwidth', (int) $args['width'], $provider ); $provider = add_query_arg( 'maxheight', (int) $args['height'], $provider ); $provider = add_query_arg( 'url', urlencode($url), $provider ); /** * Filters the oEmbed URL to be fetched. * * @since 2.9.0 * * @param string $provider URL of the oEmbed provider. * @param string $url URL of the content to be embedded. * @param array $args Optional arguments, usually passed from a shortcode. */ $provider = apply_filters( 'oembed_fetch_url', $provider, $url, $args ); foreach ( array( 'json', 'xml' ) as $format ) { $result = $this->_fetch_with_format( $provider, $format ); if ( is_wp_error( $result ) && 'not-implemented' == $result->get_error_code() ) continue; return ( $result && ! is_wp_error( $result ) ) ? $result : false; } return false; } /** * Fetches result from an oEmbed provider for a specific format and complete provider URL * * @since 3.0.0 * @access private * * @param string $provider_url_with_args URL to the provider with full arguments list (url, maxheight, etc.) * @param string $format Format to use * @return false|object|WP_Error False on failure, otherwise the result in the form of an object. */ private function _fetch_with_format( $provider_url_with_args, $format ) { $provider_url_with_args = add_query_arg( 'format', $format, $provider_url_with_args ); /** This filter is documented in wp-includes/class-oembed.php */ $args = apply_filters( 'oembed_remote_get_args', array(), $provider_url_with_args ); $response = wp_safe_remote_get( $provider_url_with_args, $args ); if ( 501 == wp_remote_retrieve_response_code( $response ) ) return new WP_Error( 'not-implemented' ); if ( ! $body = wp_remote_retrieve_body( $response ) ) return false; $parse_method = "_parse_$format"; return $this->$parse_method( $body ); } /** * Parses a json response body. * * @since 3.0.0 * @access private * * @param string $response_body * @return object|false */ private function _parse_json( $response_body ) { $data = json_decode( trim( $response_body ) ); return ( $data && is_object( $data ) ) ? $data : false; } /** * Parses an XML response body. * * @since 3.0.0 * @access private * * @param string $response_body * @return object|false */ private function _parse_xml( $response_body ) { if ( ! function_exists( 'libxml_disable_entity_loader' ) ) return false; $loader = libxml_disable_entity_loader( true ); $errors = libxml_use_internal_errors( true ); $return = $this->_parse_xml_body( $response_body ); libxml_use_internal_errors( $errors ); libxml_disable_entity_loader( $loader ); return $return; } /** * Serves as a helper function for parsing an XML response body. * * @since 3.6.0 * @access private * * @param string $response_body * @return stdClass|false */ private function _parse_xml_body( $response_body ) { if ( ! function_exists( 'simplexml_import_dom' ) || ! class_exists( 'DOMDocument', false ) ) return false; $dom = new DOMDocument; $success = $dom->loadXML( $response_body ); if ( ! $success ) return false; if ( isset( $dom->doctype ) ) return false; foreach ( $dom->childNodes as $child ) { if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType ) return false; } $xml = simplexml_import_dom( $dom ); if ( ! $xml ) return false; $return = new stdClass; foreach ( $xml as $key => $value ) { $return->$key = (string) $value; } return $return; } /** * Converts a data object from WP_oEmbed::fetch() and returns the HTML. * * @since 2.9.0 * @access public * * @param object $data A data object result from an oEmbed provider. * @param string $url The URL to the content that is desired to be embedded. * @return false|string False on error, otherwise the HTML needed to embed. */ public function data2html( $data, $url ) { if ( ! is_object( $data ) || empty( $data->type ) ) return false; $return = false; switch ( $data->type ) { case 'photo': if ( empty( $data->url ) || empty( $data->width ) || empty( $data->height ) ) break; if ( ! is_string( $data->url ) || ! is_numeric( $data->width ) || ! is_numeric( $data->height ) ) break; $title = ! empty( $data->title ) && is_string( $data->title ) ? $data->title : ''; $return = '' . esc_attr($title) . ''; break; case 'video': case 'rich': if ( ! empty( $data->html ) && is_string( $data->html ) ) $return = $data->html; break; case 'link': if ( ! empty( $data->title ) && is_string( $data->title ) ) $return = '' . esc_html( $data->title ) . ''; break; default: $return = false; } /** * Filters the returned oEmbed HTML. * * Use this filter to add support for custom data types, or to filter the result. * * @since 2.9.0 * * @param string $return The returned oEmbed HTML. * @param object $data A data object result from an oEmbed provider. * @param string $url The URL of the content to be embedded. */ return apply_filters( 'oembed_dataparse', $return, $data, $url ); } /** * Strips any new lines from the HTML. * * @since 2.9.0 as strip_scribd_newlines() * @since 3.0.0 * @access public * * @param string $html Existing HTML. * @param object $data Data object from WP_oEmbed::data2html() * @param string $url The original URL passed to oEmbed. * @return string Possibly modified $html */ public function _strip_newlines( $html, $data, $url ) { if ( false === strpos( $html, "\n" ) ) { return $html; } $count = 1; $found = array(); $token = '__PRE__'; $search = array( "\t", "\n", "\r", ' ' ); $replace = array( '__TAB__', '__NL__', '__CR__', '__SPACE__' ); $tokenized = str_replace( $search, $replace, $html ); preg_match_all( '#(]*>.+?)#i', $tokenized, $matches, PREG_SET_ORDER ); foreach ( $matches as $i => $match ) { $tag_html = str_replace( $replace, $search, $match[0] ); $tag_token = $token . $i; $found[ $tag_token ] = $tag_html; $html = str_replace( $tag_html, $tag_token, $html, $count ); } $replaced = str_replace( $replace, $search, $html ); $stripped = str_replace( array( "\r\n", "\n" ), '', $replaced ); $pre = array_values( $found ); $tokens = array_keys( $found ); return str_replace( $tokens, $pre, $stripped ); } } /** * Requests for PHP * * Inspired by Requests for Python. * * Based on concepts from SimplePie_File, RequestCore and WP_Http. * * @package Requests */ /** * Requests for PHP * * Inspired by Requests for Python. * * Based on concepts from SimplePie_File, RequestCore and WP_Http. * * @package Requests */ class Requests { /** * POST method * * @var string */ const POST = 'POST'; /** * PUT method * * @var string */ const PUT = 'PUT'; /** * GET method * * @var string */ const GET = 'GET'; /** * HEAD method * * @var string */ const HEAD = 'HEAD'; /** * DELETE method * * @var string */ const DELETE = 'DELETE'; /** * OPTIONS method * * @var string */ const OPTIONS = 'OPTIONS'; /** * TRACE method * * @var string */ const TRACE = 'TRACE'; /** * PATCH method * * @link https://tools.ietf.org/html/rfc5789 * @var string */ const PATCH = 'PATCH'; /** * Default size of buffer size to read streams * * @var integer */ const BUFFER_SIZE = 1160; /** * Current version of Requests * * @var string */ const VERSION = '1.7'; /** * Registered transport classes * * @var array */ protected static $transports = array(); /** * Selected transport name * * Use {@see get_transport()} instead * * @var array */ public static $transport = array(); /** * Default certificate path. * * @see Requests::get_certificate_path() * @see Requests::set_certificate_path() * * @var string */ protected static $certificate_path; /** * This is a static class, do not instantiate it * * @codeCoverageIgnore */ private function __construct() {} /** * Autoloader for Requests * * Register this with {@see register_autoloader()} if you'd like to avoid * having to create your own. * * (You can also use `spl_autoload_register` directly if you'd prefer.) * * @codeCoverageIgnore * * @param string $class Class name to load */ public static function autoloader($class) { // Check that the class starts with "Requests" if (strpos($class, 'Requests') !== 0) { return; } $file = str_replace('_', '/', $class); if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) { require_once(dirname(__FILE__) . '/' . $file . '.php'); } } /** * Register the built-in autoloader * * @codeCoverageIgnore */ public static function register_autoloader() { spl_autoload_register(array('Requests', 'autoloader')); } /** * Register a transport * * @param string $transport Transport class to add, must support the Requests_Transport interface */ public static function add_transport($transport) { if (empty(self::$transports)) { self::$transports = array( 'Requests_Transport_cURL', 'Requests_Transport_fsockopen', ); } self::$transports = array_merge(self::$transports, array($transport)); } /** * Get a working transport * * @throws Requests_Exception If no valid transport is found (`notransport`) * @return Requests_Transport */ protected static function get_transport($capabilities = array()) { // Caching code, don't bother testing coverage // @codeCoverageIgnoreStart // array of capabilities as a string to be used as an array key ksort($capabilities); $cap_string = serialize($capabilities); // Don't search for a transport if it's already been done for these $capabilities if (isset(self::$transport[$cap_string]) && self::$transport[$cap_string] !== null) { return new self::$transport[$cap_string](); } // @codeCoverageIgnoreEnd if (empty(self::$transports)) { self::$transports = array( 'Requests_Transport_cURL', 'Requests_Transport_fsockopen', ); } // Find us a working transport foreach (self::$transports as $class) { if (!class_exists($class)) { continue; } $result = call_user_func(array($class, 'test'), $capabilities); if ($result) { self::$transport[$cap_string] = $class; break; } } if (self::$transport[$cap_string] === null) { throw new Requests_Exception('No working transports found', 'notransport', self::$transports); } return new self::$transport[$cap_string](); } /**#@+ * @see request() * @param string $url * @param array $headers * @param array $options * @return Requests_Response */ /** * Send a GET request */ public static function get($url, $headers = array(), $options = array()) { return self::request($url, $headers, null, self::GET, $options); } /** * Send a HEAD request */ public static function head($url, $headers = array(), $options = array()) { return self::request($url, $headers, null, self::HEAD, $options); } /** * Send a DELETE request */ public static function delete($url, $headers = array(), $options = array()) { return self::request($url, $headers, null, self::DELETE, $options); } /** * Send a TRACE request */ public static function trace($url, $headers = array(), $options = array()) { return self::request($url, $headers, null, self::TRACE, $options); } /**#@-*/ /**#@+ * @see request() * @param string $url * @param array $headers * @param array $data * @param array $options * @return Requests_Response */ /** * Send a POST request */ public static function post($url, $headers = array(), $data = array(), $options = array()) { return self::request($url, $headers, $data, self::POST, $options); } /** * Send a PUT request */ public static function put($url, $headers = array(), $data = array(), $options = array()) { return self::request($url, $headers, $data, self::PUT, $options); } /** * Send an OPTIONS request */ public static function options($url, $headers = array(), $data = array(), $options = array()) { return self::request($url, $headers, $data, self::OPTIONS, $options); } /** * Send a PATCH request * * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the * specification recommends that should send an ETag * * @link https://tools.ietf.org/html/rfc5789 */ public static function patch($url, $headers, $data = array(), $options = array()) { return self::request($url, $headers, $data, self::PATCH, $options); } /**#@-*/ /** * Main interface for HTTP requests * * This method initiates a request and sends it via a transport before * parsing. * * The `$options` parameter takes an associative array with the following * options: * * - `timeout`: How long should we wait for a response? * Note: for cURL, a minimum of 1 second applies, as DNS resolution * operates at second-resolution only. * (float, seconds with a millisecond precision, default: 10, example: 0.01) * - `connect_timeout`: How long should we wait while trying to connect? * (float, seconds with a millisecond precision, default: 10, example: 0.01) * - `useragent`: Useragent to send to the server * (string, default: php-requests/$version) * - `follow_redirects`: Should we follow 3xx redirects? * (boolean, default: true) * - `redirects`: How many times should we redirect before erroring? * (integer, default: 10) * - `blocking`: Should we block processing on this request? * (boolean, default: true) * - `filename`: File to stream the body to instead. * (string|boolean, default: false) * - `auth`: Authentication handler or array of user/password details to use * for Basic authentication * (Requests_Auth|array|boolean, default: false) * - `proxy`: Proxy details to use for proxy by-passing and authentication * (Requests_Proxy|array|string|boolean, default: false) * - `max_bytes`: Limit for the response body size. * (integer|boolean, default: false) * - `idn`: Enable IDN parsing * (boolean, default: true) * - `transport`: Custom transport. Either a class name, or a * transport object. Defaults to the first working transport from * {@see getTransport()} * (string|Requests_Transport, default: {@see getTransport()}) * - `hooks`: Hooks handler. * (Requests_Hooker, default: new Requests_Hooks()) * - `verify`: Should we verify SSL certificates? Allows passing in a custom * certificate file as a string. (Using true uses the system-wide root * certificate store instead, but this may have different behaviour * across transports.) * (string|boolean, default: library/Requests/Transport/cacert.pem) * - `verifyname`: Should we verify the common name in the SSL certificate? * (boolean: default, true) * - `data_format`: How should we send the `$data` parameter? * (string, one of 'query' or 'body', default: 'query' for * HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH) * * @throws Requests_Exception On invalid URLs (`nonhttp`) * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type (use Requests constants) * @param array $options Options for the request (see description for more information) * @return Requests_Response */ public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) { if (empty($options['type'])) { $options['type'] = $type; } $options = array_merge(self::get_default_options(), $options); self::set_defaults($url, $headers, $data, $type, $options); $options['hooks']->dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options)); if (!empty($options['transport'])) { $transport = $options['transport']; if (is_string($options['transport'])) { $transport = new $transport(); } } else { $need_ssl = (0 === stripos($url, 'https://')); $capabilities = array('ssl' => $need_ssl); $transport = self::get_transport($capabilities); } $response = $transport->request($url, $headers, $data, $options); $options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options)); return self::parse_response($response, $url, $headers, $data, $options); } /** * Send multiple HTTP requests simultaneously * * The `$requests` parameter takes an associative or indexed array of * request fields. The key of each request can be used to match up the * request with the returned data, or with the request passed into your * `multiple.request.complete` callback. * * The request fields value is an associative array with the following keys: * * - `url`: Request URL Same as the `$url` parameter to * {@see Requests::request} * (string, required) * - `headers`: Associative array of header fields. Same as the `$headers` * parameter to {@see Requests::request} * (array, default: `array()`) * - `data`: Associative array of data fields or a string. Same as the * `$data` parameter to {@see Requests::request} * (array|string, default: `array()`) * - `type`: HTTP request type (use Requests constants). Same as the `$type` * parameter to {@see Requests::request} * (string, default: `Requests::GET`) * - `cookies`: Associative array of cookie name to value, or cookie jar. * (array|Requests_Cookie_Jar) * * If the `$options` parameter is specified, individual requests will * inherit options from it. This can be used to use a single hooking system, * or set all the types to `Requests::POST`, for example. * * In addition, the `$options` parameter takes the following global options: * * - `complete`: A callback for when a request is complete. Takes two * parameters, a Requests_Response/Requests_Exception reference, and the * ID from the request array (Note: this can also be overridden on a * per-request basis, although that's a little silly) * (callback) * * @param array $requests Requests data (see description for more information) * @param array $options Global and default options (see {@see Requests::request}) * @return array Responses (either Requests_Response or a Requests_Exception object) */ public static function request_multiple($requests, $options = array()) { $options = array_merge(self::get_default_options(true), $options); if (!empty($options['hooks'])) { $options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); if (!empty($options['complete'])) { $options['hooks']->register('multiple.request.complete', $options['complete']); } } foreach ($requests as $id => &$request) { if (!isset($request['headers'])) { $request['headers'] = array(); } if (!isset($request['data'])) { $request['data'] = array(); } if (!isset($request['type'])) { $request['type'] = self::GET; } if (!isset($request['options'])) { $request['options'] = $options; $request['options']['type'] = $request['type']; } else { if (empty($request['options']['type'])) { $request['options']['type'] = $request['type']; } $request['options'] = array_merge($options, $request['options']); } self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']); // Ensure we only hook in once if ($request['options']['hooks'] !== $options['hooks']) { $request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple')); if (!empty($request['options']['complete'])) { $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']); } } } unset($request); if (!empty($options['transport'])) { $transport = $options['transport']; if (is_string($options['transport'])) { $transport = new $transport(); } } else { $transport = self::get_transport(); } $responses = $transport->request_multiple($requests, $options); foreach ($responses as $id => &$response) { // If our hook got messed with somehow, ensure we end up with the // correct response if (is_string($response)) { $request = $requests[$id]; self::parse_multiple($response, $request); $request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id)); } } return $responses; } /** * Get the default options * * @see Requests::request() for values returned by this method * @param boolean $multirequest Is this a multirequest? * @return array Default option values */ protected static function get_default_options($multirequest = false) { $defaults = array( 'timeout' => 10, 'connect_timeout' => 10, 'useragent' => 'php-requests/' . self::VERSION, 'protocol_version' => 1.1, 'redirected' => 0, 'redirects' => 10, 'follow_redirects' => true, 'blocking' => true, 'type' => self::GET, 'filename' => false, 'auth' => false, 'proxy' => false, 'cookies' => false, 'max_bytes' => false, 'idn' => true, 'hooks' => null, 'transport' => null, 'verify' => Requests::get_certificate_path(), 'verifyname' => true, ); if ($multirequest !== false) { $defaults['complete'] = null; } return $defaults; } /** * Get default certificate path. * * @return string Default certificate path. */ public static function get_certificate_path() { if ( ! empty( Requests::$certificate_path ) ) { return Requests::$certificate_path; } return dirname(__FILE__) . '/Requests/Transport/cacert.pem'; } /** * Set default certificate path. * * @param string $path Certificate path, pointing to a PEM file. */ public static function set_certificate_path( $path ) { Requests::$certificate_path = $path; } /** * Set the default values * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type * @param array $options Options for the request * @return array $options */ protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) { if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) { throw new Requests_Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url); } if (empty($options['hooks'])) { $options['hooks'] = new Requests_Hooks(); } if (is_array($options['auth'])) { $options['auth'] = new Requests_Auth_Basic($options['auth']); } if ($options['auth'] !== false) { $options['auth']->register($options['hooks']); } if (is_string($options['proxy']) || is_array($options['proxy'])) { $options['proxy'] = new Requests_Proxy_HTTP($options['proxy']); } if ($options['proxy'] !== false) { $options['proxy']->register($options['hooks']); } if (is_array($options['cookies'])) { $options['cookies'] = new Requests_Cookie_Jar($options['cookies']); } elseif (empty($options['cookies'])) { $options['cookies'] = new Requests_Cookie_Jar(); } if ($options['cookies'] !== false) { $options['cookies']->register($options['hooks']); } if ($options['idn'] !== false) { $iri = new Requests_IRI($url); $iri->host = Requests_IDNAEncoder::encode($iri->ihost); $url = $iri->uri; } // Massage the type to ensure we support it. $type = strtoupper($type); if (!isset($options['data_format'])) { if (in_array($type, array(self::HEAD, self::GET, self::DELETE))) { $options['data_format'] = 'query'; } else { $options['data_format'] = 'body'; } } } /** * HTTP response parser * * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`) * @throws Requests_Exception On missing head/body separator (`noversion`) * @throws Requests_Exception On missing head/body separator (`toomanyredirects`) * * @param string $headers Full response text including headers and body * @param string $url Original request URL * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects * @return Requests_Response */ protected static function parse_response($headers, $url, $req_headers, $req_data, $options) { $return = new Requests_Response(); if (!$options['blocking']) { return $return; } $return->raw = $headers; $return->url = $url; if (!$options['filename']) { if (($pos = strpos($headers, "\r\n\r\n")) === false) { // Crap! throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator'); } $headers = substr($return->raw, 0, $pos); $return->body = substr($return->raw, $pos + strlen("\n\r\n\r")); } else { $return->body = ''; } // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) $headers = str_replace("\r\n", "\n", $headers); // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2) $headers = preg_replace('/\n[ \t]/', ' ', $headers); $headers = explode("\n", $headers); preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches); if (empty($matches)) { throw new Requests_Exception('Response could not be parsed', 'noversion', $headers); } $return->protocol_version = (float) $matches[1]; $return->status_code = (int) $matches[2]; if ($return->status_code >= 200 && $return->status_code < 300) { $return->success = true; } foreach ($headers as $header) { list($key, $value) = explode(':', $header, 2); $value = trim($value); preg_replace('#(\s+)#i', ' ', $value); $return->headers[$key] = $value; } if (isset($return->headers['transfer-encoding'])) { $return->body = self::decode_chunked($return->body); unset($return->headers['transfer-encoding']); } if (isset($return->headers['content-encoding'])) { $return->body = self::decompress($return->body); } //fsockopen and cURL compatibility if (isset($return->headers['connection'])) { unset($return->headers['connection']); } $options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options)); if ($return->is_redirect() && $options['follow_redirects'] === true) { if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) { if ($return->status_code === 303) { $options['type'] = self::GET; } $options['redirected']++; $location = $return->headers['location']; if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) { // relative redirect, for compatibility make it absolute $location = Requests_IRI::absolutize($url, $location); $location = $location->uri; } $hook_args = array( &$location, &$req_headers, &$req_data, &$options, $return ); $options['hooks']->dispatch('requests.before_redirect', $hook_args); $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); $redirected->history[] = $return; return $redirected; } elseif ($options['redirected'] >= $options['redirects']) { throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return); } } $return->redirects = $options['redirected']; $options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options)); return $return; } /** * Callback for `transport.internal.parse_response` * * Internal use only. Converts a raw HTTP response to a Requests_Response * while still executing a multiple request. * * @param string $response Full response text including headers and body (will be overwritten with Response instance) * @param array $request Request data as passed into {@see Requests::request_multiple()} * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object */ public static function parse_multiple(&$response, $request) { try { $url = $request['url']; $headers = $request['headers']; $data = $request['data']; $options = $request['options']; $response = self::parse_response($response, $url, $headers, $data, $options); } catch (Requests_Exception $e) { $response = $e; } } /** * Decoded a chunked body as per RFC 2616 * * @see https://tools.ietf.org/html/rfc2616#section-3.6.1 * @param string $data Chunked body * @return string Decoded body */ protected static function decode_chunked($data) { if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) { return $data; } $decoded = ''; $encoded = $data; while (true) { $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches); if (!$is_chunked) { // Looks like it's not chunked after all return $data; } $length = hexdec(trim($matches[1])); if ($length === 0) { // Ignore trailer headers return $decoded; } $chunk_length = strlen($matches[0]); $decoded .= substr($encoded, $chunk_length, $length); $encoded = substr($encoded, $chunk_length + $length + 2); if (trim($encoded) === '0' || empty($encoded)) { return $decoded; } } // We'll never actually get down here // @codeCoverageIgnoreStart } // @codeCoverageIgnoreEnd /** * Convert a key => value array to a 'key: value' array for headers * * @param array $array Dictionary of header values * @return array List of headers */ public static function flatten($array) { $return = array(); foreach ($array as $key => $value) { $return[] = sprintf('%s: %s', $key, $value); } return $return; } /** * Convert a key => value array to a 'key: value' array for headers * * @codeCoverageIgnore * @deprecated Misspelling of {@see Requests::flatten} * @param array $array Dictionary of header values * @return array List of headers */ public static function flattern($array) { return self::flatten($array); } /** * Decompress an encoded body * * Implements gzip, compress and deflate. Guesses which it is by attempting * to decode. * * @param string $data Compressed data in one of the above formats * @return string Decompressed string */ public static function decompress($data) { if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") { // Not actually compressed. Probably cURL ruining this for us. return $data; } if (function_exists('gzdecode') && ($decoded = @gzdecode($data)) !== false) { return $decoded; } elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) { return $decoded; } elseif (($decoded = self::compatible_gzinflate($data)) !== false) { return $decoded; } elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) { return $decoded; } return $data; } /** * Decompression of deflated string while staying compatible with the majority of servers. * * Certain Servers will return deflated data with headers which PHP's gzinflate() * function cannot handle out of the box. The following function has been created from * various snippets on the gzinflate() PHP documentation. * * Warning: Magic numbers within. Due to the potential different formats that the compressed * data may be returned in, some "magic offsets" are needed to ensure proper decompression * takes place. For a simple progmatic way to determine the magic offset in use, see: * https://core.trac.wordpress.org/ticket/18273 * * @since 2.8.1 * @link https://core.trac.wordpress.org/ticket/18273 * @link https://secure.php.net/manual/en/function.gzinflate.php#70875 * @link https://secure.php.net/manual/en/function.gzinflate.php#77336 * * @param string $gzData String to decompress. * @return string|bool False on failure. */ public static function compatible_gzinflate($gzData) { // Compressed data might contain a full zlib header, if so strip it for // gzinflate() if (substr($gzData, 0, 3) == "\x1f\x8b\x08") { $i = 10; $flg = ord(substr($gzData, 3, 1)); if ($flg > 0) { if ($flg & 4) { list($xlen) = unpack('v', substr($gzData, $i, 2)); $i = $i + 2 + $xlen; } if ($flg & 8) { $i = strpos($gzData, "\0", $i) + 1; } if ($flg & 16) { $i = strpos($gzData, "\0", $i) + 1; } if ($flg & 2) { $i = $i + 2; } } $decompressed = self::compatible_gzinflate(substr($gzData, $i)); if (false !== $decompressed) { return $decompressed; } } // If the data is Huffman Encoded, we must first strip the leading 2 // byte Huffman marker for gzinflate() // The response is Huffman coded by many compressors such as // java.util.zip.Deflater, Ruby’s Zlib::Deflate, and .NET's // System.IO.Compression.DeflateStream. // // See https://decompres.blogspot.com/ for a quick explanation of this // data type $huffman_encoded = false; // low nibble of first byte should be 0x08 list(, $first_nibble) = unpack('h', $gzData); // First 2 bytes should be divisible by 0x1F list(, $first_two_bytes) = unpack('n', $gzData); if (0x08 == $first_nibble && 0 == ($first_two_bytes % 0x1F)) { $huffman_encoded = true; } if ($huffman_encoded) { if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) { return $decompressed; } } if ("\x50\x4b\x03\x04" == substr($gzData, 0, 4)) { // ZIP file format header // Offset 6: 2 bytes, General-purpose field // Offset 26: 2 bytes, filename length // Offset 28: 2 bytes, optional field length // Offset 30: Filename field, followed by optional field, followed // immediately by data list(, $general_purpose_flag) = unpack('v', substr($gzData, 6, 2)); // If the file has been compressed on the fly, 0x08 bit is set of // the general purpose field. We can use this to differentiate // between a compressed document, and a ZIP file $zip_compressed_on_the_fly = (0x08 == (0x08 & $general_purpose_flag)); if (!$zip_compressed_on_the_fly) { // Don't attempt to decode a compressed zip file return $gzData; } // Determine the first byte of data, based on the above ZIP header // offsets: $first_file_start = array_sum(unpack('v2', substr($gzData, 26, 4))); if (false !== ($decompressed = @gzinflate(substr($gzData, 30 + $first_file_start)))) { return $decompressed; } return false; } // Finally fall back to straight gzinflate if (false !== ($decompressed = @gzinflate($gzData))) { return $decompressed; } // Fallback for all above failing, not expected, but included for // debugging and preventing regressions and to track stats if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) { return $decompressed; } return false; } public static function match_domain($host, $reference) { // Check for a direct match if ($host === $reference) { return true; } // Calculate the valid wildcard match if the host is not an IP address // Also validates that the host has 3 parts or more, as per Firefox's // ruleset. $parts = explode('.', $host); if (ip2long($host) === false && count($parts) >= 3) { $parts[0] = '*'; $wildcard = implode('.', $parts); if ($wildcard === $reference) { return true; } } return false; } }