As I noted on a comment and @toscho wrote in his answer, your code works if used after wp_loaded
hook. The reason why it works for core post types if used on earlier hooks is WordPress register core post types 2 times: first time just after 'mu_plugins_loaded'
hook and then again on ‘init’ hook (reference).
That said, if you want to use a solution that make no use of pseudo-private variables you can rely on the functions that WordPress has for the scope: get_post_types
and post_type_supports
, possibly using a sort of cache to improve performance on subsequents calls on same request, something like this:
function get_post_types_with_support( $feature ) {
static $supports;
if ( ! isset( $supports[$feature] ) ) {
if ( ! did_action( 'wp_loaded' ) && current_filter() !== 'wp_loaded' ) {
return new WP_Error( 'too-early', 'Are you in a hurry?' );
}
$supports[$feature] = array_filter( array_map( function( $type ) use( $feature ) {
if ( post_type_supports( $type, $feature ) ) return $type;
}, array_values( get_post_types() ) ) );
}
return $supports[$feature];
}