Make WordPress Core

Opened 14 years ago

Closed 12 years ago

Last modified 12 years ago

#12966 closed defect (bug) (fixed)

get_post_types returning more than desired results

Reported by: michaelh's profile michaelh Owned by:
Milestone: 3.0 Priority: normal
Severity: normal Version: 3.0
Component: Posts, Post Types Keywords: has-patch tested
Focuses: Cc:

Description

In addition to the desired custom post types, other extraneous post types such as posts, pages, and attachments, are being returned with this get_post_types example:

<?php 
//get list of public queryable, custom post types
$args=array(
  'publicly_queryable' => true,
  '_builtin' => false
);
$output = 'objects'; // names or objects
$post_types=get_post_types($args,$output); 
  foreach ($post_types  as $post_type ) {
    echo "<pre>"; print_r($post_type); echo "</pre>";
  }
?>

Using this fares no better:

$args=array(
  'public' => true,
  '_builtin' => false
);

Attachments (3)

12966.diff (666 bytes) - added by sivel 14 years ago.
Fixes the function to follow the way it is documented
12966.2.diff (3.5 KB) - added by scribu 14 years ago.
introduce wp_filter_object_list()
12966.3.diff (7.8 KB) - added by scribu 14 years ago.
add $operator argument

Download all attachments as: .zip

Change History (27)

#1 @scribu
14 years ago

  • Keywords reporter-feedback added
  • Milestone set to 3.0

Please provide the output of this code:

global $wp_post_types;

print_r($wp_post_types);

$args=array(
  'public' => true,
  '_builtin' => false
);
$post_types = get_post_types($args, $output);

print_r($post_types);

#2 @nacin
14 years ago

Not near my dev machine to test, but I also saw something like this. I think I was using public and show_ui at the same time, and I was getting incorrect results.

#4 @scribu
14 years ago

Sorry, I forgot to mention that you should use "View Page Source" so that spaces are preserved.

#7 @michaelh
14 years ago

Here's the custom post types from my functions.php

register_post_type('property', array(
	'label' => __('Real Estate'),
	'singular_label' => __('Property'),
	'public' => true,
	'show_ui' => true, // UI in admin panel
	'capability_type' => 'post',
	'hierarchical' => false,
	'rewrite' => array("slug" => "property"), // Permalinks format
	'supports' => array('title','author')
));

register_post_type('podcast', array(
	'label' => __('Podcasts'),
	'singular_label' => __('Podcast'),
	'public' => true,
	'show_ui' => true,
	'capability_type' => 'post',
	'hierarchical' => false,
	'rewrite' => false,
	'query_var' => false,
	'supports' => array('title', 'editor', 'author')
));

register_post_type('classified', array(
	'label' => 'Classifieds',
	'singular_label' => 'Classified',
	'_builtin' => false,
	'public' => true,
	'publicly_queryable' => true,
	'show_ui' => true, // UI in admin panel
	'capability_type' => 'post'
)); 

#8 @sivel
14 years ago

The problem is with the way the function is documented and how it works. The docs say "Only post types having attributes that match all arguments are returned". However it really returns all post types that match at least 1 of the args. I have a patch coming that fixes this function to perform the way I think it should as well as match the documentation.

@sivel
14 years ago

Fixes the function to follow the way it is documented

#9 @sivel
14 years ago

  • Cc matt@… added
  • Keywords has-patch added; reporter-feedback removed

This patch counts the number of intersections found and compares it to the number of arguments that were passed instead of just checking that intersections were found.

#10 @nacin
14 years ago

This probably also effects get_taxonomies().

@scribu
14 years ago

introduce wp_filter_object_list()

#11 follow-up: @scribu
14 years ago

Thanks, michaelh.

Heh, I only saw sivel's patch now.

I took it a step further and created a more general function that's used by both get_post_types() and get_taxonomies().

#12 in reply to: ↑ 11 @sivel
14 years ago

I took it a step further and created a more general function that's used by both get_post_types() and get_taxonomies().

At least we took the same approach to fixing it. Good catch on taxonomies, I had only been working on post types and it didn't occur to me to test taxonomies.

#13 @nacin
14 years ago

Looks like get_post_stati() already performs the count correctly. I would suggest moving it over to the helper, but it actually allows for an OR operator, which is something we could potentially introduce to these as well.

Standardization of arguments and functionality is a developer's best friend when they actually have to leverage the API.

#14 @rovo89
14 years ago

An alternative to

if ( count(array_intersect_assoc(get_object_vars($obj), $args)) == $count )

would be

if ( empty(array_diff_assoc($args, get_object_vars($obj))) )

which should provide the same functionality, but might be slightly faster.

#15 @nacin
14 years ago

Can't call empty() like that, needs to be a variable. Good thought though and there's a few ways to take that and make it work. But we're dealing with negligible performance at that point.

#16 @michaelh
14 years ago

Thanks both scribu and sivel.

Applied 12966.2.diff and using

$output = 'objects'; // names or objects
$post_types=get_post_types('',$output); 

get this error:

Warning: array_intersect_assoc() [function.array-intersect-assoc]: Argument #2 is not an array in C:\xampp\htdocs\wp30\wp-includes\functions.php  on line 2929

@scribu
14 years ago

add $operator argument

#17 @scribu
14 years ago

So, 12966.3.diff:

  • adds an empty($args) check to prevent the warning mentioned by michaelh above.
  • adds the $operator argument to wp_filter_object_list(), get_post_types() and get_taxonomies()
  • refactors get_post_stati() to use wp_filter_object_list()

Seeing that get_post_stati() was only introduced in 3.0, I took the liberty of switching the default value for the $operator argument from 'or' to 'and'. This makes it consistent with get_post_types() and get_taxonomies() and it's also the more common use-case.

I've double-checked that this change doesn't affect it's usage in core.

#18 @michaelh
14 years ago

12966.3 works good with a variety of arguments, including $operator, using get_post_types()

#19 @scribu
14 years ago

  • Keywords tested added

I'm pretty happy with it.

#20 @michaelh
14 years ago

  • Component changed from Template to Post Types

#21 @nacin
14 years ago

  • Resolution set to fixed
  • Status changed from new to closed

[14108]

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.

#22 @Ov3rfly
12 years ago

  • Keywords 2nd-opinion added
  • Resolution fixed deleted
  • Status changed from closed to reopened
  • Version changed from 3.0 to 3.2.1

Seems still not to work as expected, example:

		$args = array(
			'public'   => true,
			'_builtin' => false,
			'taxonomies' => array('post_tag')
		);
		$post_types = get_post_types($args, 'objects'); 
		print_r($post_types);

Expected results: All public custom post types with (at least) taxonomy 'post_tag'.

Actual results: All public custom post types, also if they do not have 'post_tag' set as taxonomy.

Result of above print_r() http://pastebin.com/4dL7i0DU

Note the empty taxonomies at post type slider:

    ...
    [slider] => stdClass Object
        (
            ...
            [taxonomies] => Array
                (
                )
            ...

http://codex.wordpress.org/Function_Reference/get_post_types lists 'taxonomies' as valid argument.

Related older thread, but no discussion there: http://wordpress.org/support/topic/get_post_types-returns-more-than-expected

#23 @ocean90
12 years ago

  • Keywords 2nd-opinion removed
  • Resolution set to fixed
  • Status changed from reopened to closed
  • Version changed from 3.2.1 to 3.0

This ticket was closed on a completed milestone. New ticket, please.

Note: See TracTickets for help on using tickets.