Support

Account

Home Forums Backend Issues (wp-admin) Post object option ignores a custom post type Reply To: Post object option ignores a custom post type

  • Hi,

    I don’t know if we are sharing the same issue (and for me, the issue stretches further back than 5.2.5) but I’ve figured out mine.

    The Context:

    The project I’m currently working on uses Polylang for translations. Custom fields aren’t set to be translated, their data is synced manually.

    I have a post object setup to retrieve posts from two custom post types: partner and sponsor. These post types aren’t configured to be multilingual.

    The Issue:

    In acf_field_post_object::render_field(), if there’s a saved value, ACF will retrieve all posts matching the saved value (in order to pre-populate the rendered field).

    
    $posts = acf_get_posts(array(
    	'post__in' => $field['value']
    ));
    

    Unfortunately, this returns an empty array because acf_get_posts() will default to loading from all available post types. In my case, acf_get_post_types() returns: post, page, attachment, partner, and sponsor.

    And this is the key problem: post and page are configured to be multilingual. This triggers Polylang to add a condition to fetch posts in the current language which the non-multilingual post types can’t fulfill.

    First Solution:

    Require ACF to pass along the filtered list of post types:

    
    $posts = acf_get_posts(array(
    	'post__in' => $field['value'],
    	'post_type' => $field['post_type']
    ));
    

    The one downside of this is if the list of filtered post types changes (e.g., a post type is removed), it will affect any currently saved value assigned to that now-removed post type.

    Second Solution:

    Intercept Polylang before it adds that language condition to the WP_query. I accomplish this using a backtrace to figure out if the WP_query was called by acf_get_posts() by way of acf_field->render_field().

    **Updated 2015-05-21T17:22-05:00**

    
    add_action( 'pre_get_posts', function ( &$wp_query ) {
    	$is_acf_get_posts = (
    		   ( $e = new Exception )
    		&& ( $trace = $e->getTraceAsString() )
    		&& false !== strpos( $trace, 'acf_get_posts(Array)' )
    		&& (
    			   (   is_admin() && false !== strpos( $trace, '->render_field(Array)' ) )
    			|| ( ! is_admin() && false !== strpos( $trace, '->format_value(' ) )
    		)
    	);
    
    	if ( $is_acf_get_posts && pll_is_not_translated_post_type( $wp_query->get('post_type') ) ) {
    		pll_remove_language_query_var( $wp_query );
    	}
    }, 9 );
    
    function pll_is_not_translated_post_type( $post_type ) {
    	global $polylang;
    
    	if ( isset( $polylang ) ) {
    		$pll_post_types = $polylang->model->get_translated_post_types( false );
    
    		return ( is_array( $post_type ) && array_diff( $post_type, $pll_post_types ) || in_array( $post_type, $pll_post_types ) );
    	}
    
    	return false;
    }
    
    function pll_remove_language_query_var( &$query ) {
    	$qv = &$query->query_vars;
    
    	unset( $qv['lang'] );
    
    	if ( ! empty( $qv['tax_query'] ) ) {
    		foreach ( $qv['tax_query'] as $i => $tax_query ) {
    			if ( isset( $tax_query['taxonomy'] ) && 'language' === $tax_query['taxonomy'] ) {
    				unset( $qv['tax_query'][ $i ] );
    			}
    		}
    	}
    }
    

    I made this filter very verbose just to make sure the idea is understand. I’m using a much more compact version in my project. This function can also be easily translated to your multilingual-plugin flavour (e.g., WPML).

    Cheers,