From 14916e2449bc434c7371e6e21bd9db87e703d07b Mon Sep 17 00:00:00 2001 From: nacin Date: Fri, 16 Apr 2010 14:08:58 +0000 Subject: [PATCH] Introduce the wp_filter_object_list() helper, with an $operator arg. Fixes an intersection bug in get_post_types() and get_taxonomies(). Also switches $operator default from 'or' to 'and' for get_post_stati(). props scribu, fixes #12966. git-svn-id: http://svn.automattic.com/wordpress/trunk@14108 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/functions.php | 37 ++++++++++++++++++++- wp-includes/post.php | 67 ++++++++------------------------------- wp-includes/query.php | 2 +- wp-includes/taxonomy.php | 18 ++++------- 4 files changed, 57 insertions(+), 67 deletions(-) diff --git a/wp-includes/functions.php b/wp-includes/functions.php index ebcd064ab..15f5160cb 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -2901,13 +2901,48 @@ function wp_parse_args( $args, $defaults = '' ) { * @param array|string $list * @return array Sanitized array of IDs */ -function wp_parse_id_list($list) { +function wp_parse_id_list( $list ) { if ( !is_array($list) ) $list = preg_split('/[\s,]+/', $list); return array_unique(array_map('absint', $list)); } +/** + * Filters a list of objects, based on a set of key => value arguments + * + * @since 3.0.0 + * + * @param array $list An array of objects to filter + * @param array $args An array of key => value arguments to match against each object + * @param string $operator The logical operation to perform. 'or' means only one element + * from the array needs to match; 'and' means all elements must match. The default is 'and'. + * @param bool|string $field A field from the object to place instead of the entire object + * @return array A list of objects or object fields + */ +function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) { + if ( !is_array($list) ) + return array(); + + if ( empty($args) ) + $args = array(); + + if ( empty($args) && !$field ) + return $list; // nothing to do + + $count = count($args); + + $filtered = array(); + + foreach ( $list as $key => $obj ) { + $matched = count(array_intersect_assoc(get_object_vars($obj), $args)); + if ( ('and' == $operator && $matched == $count) || ('or' == $operator && $matched <= $count) ) + $filtered[$key] = $field ? $obj->$field : $obj; + } + + return $filtered; +} + /** * Determines if default embed handlers should be loaded. * diff --git a/wp-includes/post.php b/wp-includes/post.php index bb40c2bcc..4484caf9c 100644 --- a/wp-includes/post.php +++ b/wp-includes/post.php @@ -631,42 +631,18 @@ function get_post_status_object( $post_status ) { * @see register_post_status * @see get_post_status_object * - * @param array|string $args An array of key => value arguments to match against the post statuses. - * Only post statuses having attributes that match all arguments are returned. + * @param array|string $args An array of key => value arguments to match against the post status objects. * @param string $output The type of output to return, either post status 'names' or 'objects'. 'names' is the default. - * @param string $operator Whether the elements in $args should be logicallly 'or'ed or 'and'ed together. 'or' means only one element from the array needs to match. 'and' means all elements must match. The default is 'or'. + * @param string $operator The logical operation to perform. 'or' means only one element + * from the array needs to match; 'and' means all elements must match. The default is 'and'. * @return array A list of post type names or objects */ -function get_post_stati( $args = array(), $output = 'names', $operator = 'or' ) { +function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_post_statuses; - $do_names = false; - if ( 'names' == $output ) - $do_names = true; + $field = ('names' == $output) ? 'name' : false; - if ( 'and' == $operator ) - $arg_count = count($args); - else - $arg_count = 0; - - $post_statuses = array(); - foreach ( (array) $wp_post_statuses as $post_status ) { - if ( empty($args) ) { - if ( $do_names ) - $post_statuses[] = $post_status->name; - else - $post_statuses[] = $post_status; - } elseif ( $intersect = array_intersect_assoc((array) $post_status, $args) ) { - if ( $arg_count && ( $arg_count != count($intersect) ) ) - continue; - if ( $do_names ) - $post_statuses[] = $post_status->name; - else - $post_statuses[] = $post_status; - } - } - - return $post_statuses; + return wp_filter_object_list($wp_post_statuses, $args, $operator, $field); } /** @@ -701,7 +677,7 @@ function is_post_type_hierarchical( $post = false ) { * @param mixed $the_post Optional. Post object or post ID. * @return bool|string post type or false on failure. */ -function get_post_type($the_post = false) { +function get_post_type( $the_post = false ) { global $post; if ( false === $the_post ) @@ -745,36 +721,19 @@ function get_post_type_object( $post_type ) { * @since 2.9.0 * @uses $wp_post_types * @see register_post_type - * @see get_post_types * - * @param array|string $args An array of key => value arguments to match against the post types. - * Only post types having attributes that match all arguments are returned. + * @param array|string $args An array of key => value arguments to match against the post type objects. * @param string $output The type of output to return, either post type 'names' or 'objects'. 'names' is the default. + * @param string $operator The logical operation to perform. 'or' means only one element + * from the array needs to match; 'and' means all elements must match. The default is 'and'. * @return array A list of post type names or objects */ -function get_post_types( $args = array(), $output = 'names' ) { +function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_post_types; - $do_names = false; - if ( 'names' == $output ) - $do_names = true; + $field = ('names' == $output) ? 'name' : false; - $post_types = array(); - foreach ( (array) $wp_post_types as $post_type ) { - if ( empty($args) ) { - if ( $do_names ) - $post_types[] = $post_type->name; - else - $post_types[] = $post_type; - } elseif ( array_intersect_assoc((array) $post_type, $args) ) { - if ( $do_names ) - $post_types[] = $post_type->name; - else - $post_types[] = $post_type; - } - } - - return $post_types; + return wp_filter_object_list($wp_post_types, $args, $operator, $field); } /** diff --git a/wp-includes/query.php b/wp-includes/query.php index e7e47dfd6..6b42a5d34 100644 --- a/wp-includes/query.php +++ b/wp-includes/query.php @@ -2255,7 +2255,7 @@ class WP_Query { if ( 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), 'names', 'and' ); + $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'"; } diff --git a/wp-includes/taxonomy.php b/wp-includes/taxonomy.php index 292d744d7..dc02a1777 100644 --- a/wp-includes/taxonomy.php +++ b/wp-includes/taxonomy.php @@ -67,25 +67,21 @@ add_action( 'init', 'create_initial_taxonomies', 0 ); // highest priority * @uses $wp_taxonomies * @see register_taxonomy * - * @param array $args An array of key => value arguments to match against the taxonomies. - * Only taxonomies having attributes that match all arguments are returned. + * @param array $args An array of key => value arguments to match against the taxonomy objects. * @param string $output The type of output to return, either taxonomy 'names' or 'objects'. 'names' is the default. + * @param string $operator The logical operation to perform. 'or' means only one element + * from the array needs to match; 'and' means all elements must match. The default is 'and'. * @return array A list of taxonomy names or objects */ -function get_taxonomies( $args = array(), $output = 'names' ) { +function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_taxonomies; - $taxonomies = array(); - foreach ( (array) $wp_taxonomies as $taxname => $taxobj ) - if ( empty($args) || array_intersect_assoc((array) $taxobj, $args) ) - $taxonomies[$taxname] = $taxobj; + $field = ('names' == $output) ? 'name' : false; - if ( 'names' == $output ) - return array_keys($taxonomies); - - return $taxonomies; + return wp_filter_object_list($wp_taxonomies, $args, $operator, $field); } + /** * Return all of the taxonomy names that are of $object_type. *