There appear to be a couple things at work here:
-
The
switch_to_blog()
call does not switch plugins (see ticket #14941), so if your custom post types are defined in a plugin (as they most likely are and should be), then they won’t be loaded in aswitch_to_blog()
scenario. (This is highly unlikely to changed, judging by the commentary on the ticket.) -
Also, the
get_post_types()
uses a global variable; it doesn’t grab the CPTs registered in the site you switch to, but the list from the site you started from. Global variables don’t seem to be updated onswitch_to_blog()
, presumably for reasons similar to the reasons plugins aren’t unloaded/loaded onswitch_to_blog()
.
I don’t know that there’s going to be an easy way to do what you’re trying to do, I’m afraid.
A possible work-around
register_post_type()
fires an action—registered_post_type
—as it finishes up. You should be able to use this to build a list of custom post types on a given site.
Something like this (very simple, untested code):
<?php
add_action( 'registered_post_type', 'wpse_290292_post_types', 10, 2 );
function wpse_290292_post_types( $post_type_name, $post_type_object ) {
$post_types = get_option( 'my_prefix_post_types', array() );
if (
! isset( $post_types[ $post_type_name ] )
|| $post_type_object !== $post_types[ $post_type_name ]
) {
// Adds the $post_type_object to the array if it's a) not already there or b) changed since it was added.
$post_types[ $post_type_name ] = $post_type_object;
update_option( 'my_prefix_post_types', $post_types );
}
}
?>
This will add any registered post types to the *_options
table. You’ll probably want to add in some checks to prevent adding the _builtin
post types, etc.
Once this is set up—probably as a network-enabled plugin—you should be able to get a given site’s CPTs using the my_prefix_post_types
option (feel free to rename that as needed).