Support

Account

Home Forums Search Search Results for 'pre_get_posts'

Search Results for 'pre_get_posts'

reply

  • Hi @realph

    Yes, becuase ACF is saving the checked values as a serialized array, the ‘IN’ compare will not work. The IN compare is used when the database value is a single string value, and the value used in the $meta_query is an array. This is not the data setup you have, so you should not use this.

    The pseudo code for this query is:

    
    get all posts where the meta_value for is 'a' or 
    the meta_value for is 'b' or
    the meta_value for is 'c'
    

    You can write this like so:

    
    <?php 
    
    add_action('pre_get_posts', 'my_pre_get_posts');
     
    function my_pre_get_posts( $query ) {
    
        if( is_admin() ) { return; }
     
        $meta_query = $query->get('meta_query'); // get original meta query
        
        
        // validate type
        if( empty($_GET['type']) )
        {
    	    return;
        }
        
        
        // get types as an array
        // - use explode to get an array of values from type=a|b|c
        $types = explode('|', $_GET['type']);
        
        
        // set compare for the meta_query
        // - http://codex.wordpress.org/Class_Reference/WP_Query
        $meta_query['relation'] = 'OR';
        
        
        foreach( $types as $type )
        {
    	    $meta_query[] = array(
                'key'       => 'type',
                'value'     => '"' . $type . '"',
                'compare'   => 'LIKE',
            );
        }
    	
    	
        $query->set('meta_query', $meta_query); // update the meta query args
        
        return; // always return
    }
    
    ?>
    

    Hope that helps

    Thanks
    E

  • @elliot Do you think this has anything to do with the serialized data the Checkbox Field outputs?

    Some of my books are assigned to multiple Book Types, like so:

    Book Title: Mums and Babies
    Book Type:

    • Women
    • Babies
    • Children

    Wondering if this is what’s causing the issue.

    This is where I’m at currently:

    add_action('pre_get_posts', 'my_pre_get_posts');
     
    function my_pre_get_posts( $query ) {
        if( is_admin() ) { return; }
     
        $meta_query = $query->get('meta_query'); // get original meta query
            
            if( isset($_GET['type']) ) {                        
            
            $type = '"' . $_GET['type'] . '"';      
    
            $meta_query[] = array(
                'key'       => 'type',
                'value'     => $type,
                'compare'   => 'LIKE',
            );
        }
        $query->set('meta_query', $meta_query); // update the meta query args
        return; // always return
    }

    Works with one value, but not multiple values (.com/?type=women,babies):

  • Ok, false alarm. The code above was wrong. @elliot Some people over on the Stack Exchange forum are saying I shouldn’t be using a LIKE compare, and an IN instead when using arrays.

    Not sure which is right. But when I try to use an IN compare, I get a blank page when querying my posts.

    add_action('pre_get_posts', 'my_pre_get_posts');
    function my_pre_get_posts( $query ) {
    	if( is_admin() ) {
    		return;
    	}
    	$meta_query = $query->get('meta_query');
            if( !empty($_GET['type']) ) {				
            	$type = explode('|', $_GET['type']);	
    
    	    	$meta_query[] = array(							
                    'key'		=> 'type',
                    'value'		=> $type,
                    'compare'	=> 'IN',
                );
            }
    	$query->set('meta_query', $meta_query);
    	return;	// always return
    }
    
  • @elliot *Exhale* I feel to cry! After a whole day of staring at my functions.php, I think I may have finally cracked it!

    add_action('pre_get_posts', 'my_pre_get_posts');
     
    function my_pre_get_posts( $query ) {
    	if( is_admin() ) {
    		return;
    	}
     
    	$book_format = $query->get('meta_query');
     
            if( !empty($_GET['type']) ) {
            
    	    	$book_format[] = array(
                    'key'		=> 'type',
                    'value'		=> $_GET['type'],
                    'compare'	=> 'LIKE',
                );
            }
     
    	$query->set('meta_query', $book_format);
     
    	return;
    }

    Now when I append this to my url:

    dev.com/books?=home

    it displays an archive of all my books with the ‘type’ of ‘home’. This is fantastic!

    The only problem I’m having now is, separating these in the url with the ‘|’ character doesn’t seem to yield any results. Any idea why that might be happening, or is that normal?

  • Hi @retotito

    It is possible that there is a filter in your theme or a plugin which is modifying the WP_Query args. This filter is most likely called ‘pre_get_posts’.

    Perhaps as a test, create a simple text field and enter the value ‘test’. Then change your query args to find posts where the field_name = ‘test’.

    Does this work?

    Thanks
    E

  • Just to clarify for anyone who comes across this later:

    My pre_get_posts action was setting query parameters not just for the main query (as I intended) but also the query by the Gallery plugin that gets the attachment data. These query parameters caused the get_posts query in gallery.php to return nothing.

  • What happens if you add $query->is_main_query() to your if statement?

    
    function allstar_buzzworthy_published_sort( $query ) {
            // If not the admin section
            if ( !is_admin() &&  $query->is_main_query()) {
                // If on a taxonomy page
                if ( is_tax() ) {
                    $query->set( 'meta_key', 'date_published' );
                    $query->set( 'orderby', 'meta_value' );
                    $query->set( 'order', 'DESC' );
                }
            }
        }
        add_action( 'pre_get_posts', 'allstar_buzzworthy_published_sort' );
    
  • The issue for me was specific to $query->set('s', ' ');. I added it to fix empty search queries returning a 404 page.

    I set a bunch of other query vars in the same function but going through one by one, this was the only one to cause error.

    Btw, you’re missing a single quote before date_published.

      
    function property_filters($query) {
    
      // ...
    
      /**
       * Fixes issue with blank search queries returning 404
       */
      if (!is_admin() && isset($query->query_vars['s']) && empty($query->query_vars['s'])) {
        $query->set('s', ' ');
      }
    }
    add_action('pre_get_posts', 'property_filters');
    
  • What are you doing inside your pre_get_posts action? I don’t believe it’s the pre_get_posts action that’s causing the problem. If I just have it echo out some text, get_field returns an array of images as expected. It’s when I modify the query by adding $query->set( 'meta_key', date_published' ); that I run into a problem.

  • I am also seeing the same behaviour after upgrading to Gallery 1.1.0 and ACF 4.3.0.

    With add_action('pre_get_posts'... called in functions.php, get_field for a gallery field returns an empty array.

    If I comment out the pre_get_posts action everything works as expected.

  • (This is going to be interesting to work out since we’re in basically opposite time zones)

    I will check the $post-ID in the morning when I get to the office, as well as testing a basic function, but everything else for the post is displaying properly…the name, permalink, even other metadata I’ve set using ACF and am accessing with get_field(). The ONLY thing that isn’t working is that the gallery is returning an empty array rather than an array of images.

    I am certain that the posts have gallery data, because on their individual pages the gallery is being displayed fine, and when I remove my pre_get_posts filter, the galleries show up on the correct posts.

    Thanks,
    Ryan

  • Hi @bounty_digital

    I don’t think your code is following the correct logic path for this to work.
    Your code needs to be spit up into 2 parts:

    1. Create the radio button where a user can select the category and then be redirected to the archive url with the $_GET param

    2. hook into the pre_get_posts filter and look for the $_GET param. If it exists, add the meta query in.

    I should really write a tutorial for this one, so I’m happy to write the code. This is the most simple way to get it working:

    
    <?php 
    
    $field = get_field_object("field_5039a99716d1d");
    
    ?>
    <form action="<?php echo home_url('slug/to/archive'); ?>" method="get">
    	<ul>
    	<?php foreach( $field['choices'] as $k => $v ): ?>
    		<li>
    			<label><input type="radio" name="acf_category" value="<?php echo $k; ?>" /><?php echo $v; ?></label>
    		</li>
    	<?php endforeach; ?>
    	</ul>
    	<input type="submit" value="Go" />
    </form>
    
    <?php 
    
    add_filter( 'pre_get_posts', 'my_pre_get_posts' );
    
    function my_pre_get_posts( $query ) {
    	
    	if( isset($_GET['my_custom_category']) )
    	{
    		// $query is the WP_Query object, set is simply a method of the WP_Query class that sets a query var parameter
    		$query->set( 'meta_key', 'acf_field_name' );
    		$query->set( 'meta_value', $_GET['acf_category'] );
    	}
    	return $query;
    }
    
     ?>
    

    This code has not been tested, you can see the 2 parts of code. The rest will be up to you to test it and fix any issues it contains!

    Good luck

    Thanks
    E

  • This reply has been marked as private.
  • Fixed.

    I’ve replaced the above filter with the following from here -> http://blog.rutwick.com/display-only-the-posts-authored-by-the-current-wp-user-on-the-posts-page-in-the-back-end.

    add_action('pre_get_posts', 'filter_posts_list');
    function filter_posts_list($query)
    {
        //$pagenow holds the name of the current page being viewed
         global $pagenow;
     
        //$current_user uses the get_currentuserinfo() method to get the currently logged in user's data
         global $current_user;
         get_currentuserinfo();
         
         //Shouldn't happen for the admin, but for any role with the edit_posts capability and only on the posts list page, that is edit.php
          if(!current_user_can('administrator') && current_user_can('edit_posts') && ('edit.php' == $pagenow)){
            //global $query's set() method for setting the author as the current user's id
            $query->set('author', $current_user->ID);
            }
    }
  • Update,

    i’ve narrowed it down to the fact that i’m using this code to stop anyone who is logged in as a role of school being able to see anyone elses posts.

    function posts_for_current_author($query) {
    	global $user_level;
    
    	if($query->is_admin && $user_level < 5) {
    		global $user_ID;
    		$query->set('author',  $user_ID);
    		unset($user_ID);
    	}
    	unset($user_level);
    
    	return $query;
    }
    add_filter('pre_get_posts', 'posts_for_current_author');

    If i remove that, the custom fields show fine.

    Any idea how to modify that code so it doesnt interfere with ACF?

  • Hi @Romain9p

    The only thing I can think of is that there is a filter running on the pre_get_posts which is overriding this setting.

    Hopefuly that points you in the right direction.

    Thanks
    E

  • You can use this code in your functions.php file

    // Restrict media library to show only own user files
    add_action('pre_get_posts','ml_restrict_media_library');
    function ml_restrict_media_library( $wp_query_obj ) {
    
    	global $current_user, $pagenow;
    
    	if( !is_a( $current_user, 'WP_User') )
    
    		return;
    
    	if( 'admin-ajax.php' != $pagenow || $_REQUEST['action'] != 'query-attachments' )
    
    		return;
    
    	if( !current_user_can('delete_pages') )
    
    		$wp_query_obj->set('author', $current_user->ID );
    
    	return;
    
    }
    
  • Hi,
    i solved it this way:

    if( isset($query->query_vars[‘post_type’]) && $query->query_vars[‘post_type’] == ‘acf’ ){
    return $query;
    }

    Thanks for your excellent plugin!

  • Hi @homax

    On this page, you will find examples of sorting by a custom field:
    http://www.advancedcustomfields.com/resources/getting-started/code-examples/

    To orderby a custom field value, it is very simple but you will need to read up on it here:
    http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters

    Also, these examples use the get_posts function, but you may need to use the pre_get_posts filter if you want to override the core query!

    Cheers
    E

  • Since I’m using it for the post type “course”, I changed the post_type=post into post_type=course.

    However, the count still doesn’t work (it still counts everything).

    Also, the 1st part of your code (that you last posted) doesn’t work (to show only the authors content) – while an earlier example of you did work – so I used the code below for the first part and added the “Fix post counts” count only.

    What I’m currently using (working code).

    // So authors can only see their own content (e.g. courses etc)
    function posts_for_current_author($query) {
    	
    	if( !$query->is_admin )
    		return $query;
    		
    	$screen = get_current_screen();
    	
    	if ($screen->base === 'post')
        		return $query;
    	
    	if( !current_user_can( 'activate_plugins' ) ) {
    		global $user_ID;
    		$query->set('author', $user_ID );
    		
    	}
    	return $query;
    	
    	
    }
    
    add_filter('pre_get_posts', 'posts_for_current_author');

    I haven’t been able to get the count correct, see http://d.pr/i/Ijhs.

  • oh yes, sorry… the filter call needs to be changed and the post type in the filter callback need to changed – in fact there is a bit where I commented out the post in the original – here is some changed code with comments as I can’t test it fully without setting up a new site for posts and creating users etc..

    function posts_for_current_author($query) {
    	
    	if( !$query->is_admin )
    		return $query;
    		
    	if( isset($query->query_vars['post_type']) &&  $query->query_vars['post_type'] == 'acf' )
    {
    	return $query;
    }
    		
    	
    	if( !current_user_can( 'moderate_comments' ) ) {
    		global $user_ID;
    		$query->set('author', $user_ID );
    
                    // filter for changing the numbers on the list
                    // its called for views_edit-xxx where xxx is the post/custom post type
    		add_filter('views_edit-post', 'fix_post_counts');
                    add_filter('views_upload', 'fix_media_counts');
    	}
    	return $query;
    }
    
    add_action('pre_get_posts', 'posts_for_current_author');
    
    // Fix post counts
    function fix_post_counts($views) {
        global $current_user, $wp_query;
    	
    	
    	
        unset($views['mine']);
        $types = array(
            array( 'status' =>  NULL ),
            array( 'status' => 'publish' ),
            array( 'status' => 'draft' ),
            array( 'status' => 'pending' ),
            array( 'status' => 'trash' )
        );
        foreach( $types as $type ) {
            $query = array(
                'author'      => $current_user->ID,
                // the post type/custom post type we are modifying
                'post_type'   => 'post',
    			
                'post_status' => $type['status']
            );
            $result = new WP_Query($query);
            if( $type['status'] == NULL ):
                $class = ($wp_query->query_vars['post_status'] == NULL) ? ' class="current"' : '';
                $views['all'] = sprintf(__('<a href="%s"'. $class .'>All <span class="count">(%d)</span></a>', 'all'),
                    admin_url('edit.php?post_type=post'),
                    $result->found_posts);
            elseif( $type['status'] == 'publish' ):
                $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
                $views['publish'] = sprintf(__('<a href="%s"'. $class .'>Published <span class="count">(%d)</span></a>', 'publish'),
                    admin_url('edit.php?post_status=publish&post_type=post'),
                    $result->found_posts);
            elseif( $type['status'] == 'draft' ):
                $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
                $views['draft'] = sprintf(__('<a href="%s"'. $class .'>Draft'. ((sizeof($result->posts) > 1) ? "s" : "") .' <span class="count">(%d)</span></a>', 'draft'),
                    admin_url('edit.php?post_status=draft&post_type=post'),
                    $result->found_posts);
            elseif( $type['status'] == 'pending' ):
                $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
                $views['pending'] = sprintf(__('<a href="%s"'. $class .'>Pending <span class="count">(%d)</span></a>', 'pending'),
                    admin_url('edit.php?post_status=pending&post_type=post'),
                    $result->found_posts);
            elseif( $type['status'] == 'trash' ):
                $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
                $views['trash'] = sprintf(__('<a href="%s"'. $class .'>Trash <span class="count">(%d)</span></a>', 'trash'),
                    admin_url('edit.php?post_status=trash&post_type=post'),
                    $result->found_posts);
            endif;
        }
    	
        return $views;
    }
    
  • when I checked my code it was not working although I was sure it had been before!!!

    Anyhow with a combination of things this is definitely working on my site now, you need the filters to modify the numbers of posts shown at the top of the list of posts screen.

    function listings_for_current_author($query) {
    	
    	if( !$query->is_admin )
    		return $query;
    		
    	if( isset($query->query_vars['post_type']) &&  $query->query_vars['post_type'] == 'acf' )
    {
    	return $query;
    }
    		
    	
    	if( !current_user_can( 'moderate_comments' ) ) {
    		global $user_ID;
    		$query->set('author', $user_ID );
    		add_filter('views_edit-site_listings', 'fix_listing_counts');
                    add_filter('views_upload', 'fix_listing_media_counts');
    	}
    	return $query;
    }
    
    add_action('pre_get_posts', 'listings_for_current_author');
    
    // Fix post counts
    function fix_listing_counts($views) {
        global $current_user, $wp_query;
    	/*
    	unset($views['all']);
                unset($views['publish']);
                unset($views['trash']);
    	*/
    	
    	
        unset($views['mine']);
        $types = array(
            array( 'status' =>  NULL ),
            array( 'status' => 'publish' ),
            array( 'status' => 'draft' ),
            array( 'status' => 'pending' ),
            array( 'status' => 'trash' )
        );
        foreach( $types as $type ) {
            $query = array(
                'author'      => $current_user->ID,
                //'post_type'   => 'post',
    			'post_type'   => 'site_listings',
                'post_status' => $type['status']
            );
            $result = new WP_Query($query);
            if( $type['status'] == NULL ):
                $class = ($wp_query->query_vars['post_status'] == NULL) ? ' class="current"' : '';
                $views['all'] = sprintf(__('<a href="%s"'. $class .'>All <span class="count">(%d)</span></a>', 'all'),
                    admin_url('edit.php?post_type=site_listings'),
                    $result->found_posts);
            elseif( $type['status'] == 'publish' ):
                $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
                $views['publish'] = sprintf(__('<a href="%s"'. $class .'>Published <span class="count">(%d)</span></a>', 'publish'),
                    admin_url('edit.php?post_status=publish&post_type=site_listings'),
                    $result->found_posts);
            elseif( $type['status'] == 'draft' ):
                $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
                $views['draft'] = sprintf(__('<a href="%s"'. $class .'>Draft'. ((sizeof($result->posts) > 1) ? "s" : "") .' <span class="count">(%d)</span></a>', 'draft'),
                    admin_url('edit.php?post_status=draft&post_type=site_listings'),
                    $result->found_posts);
            elseif( $type['status'] == 'pending' ):
                $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
                $views['pending'] = sprintf(__('<a href="%s"'. $class .'>Pending <span class="count">(%d)</span></a>', 'pending'),
                    admin_url('edit.php?post_status=pending&post_type=site_listings'),
                    $result->found_posts);
            elseif( $type['status'] == 'trash' ):
                $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
                $views['trash'] = sprintf(__('<a href="%s"'. $class .'>Trash <span class="count">(%d)</span></a>', 'trash'),
                    admin_url('edit.php?post_status=trash&post_type=site_listings'),
                    $result->found_posts);
            endif;
        }
    	
        return $views;
    }
    
    // Fix media counts
    function fix_listing_media_counts($views) {
        global $wpdb, $current_user, $post_mime_types, $avail_post_mime_types;
        $views = array();
        $_num_posts = array();
        $count = $wpdb->get_results( "
            SELECT post_mime_type, COUNT( * ) AS num_posts 
            FROM $wpdb->posts 
            WHERE post_type = 'attachment' 
            AND post_author = $current_user->ID 
            AND post_status != 'trash' 
            GROUP BY post_mime_type
        ", ARRAY_A );
        foreach( $count as $row )
            $_num_posts[$row['post_mime_type']] = $row['num_posts'];
        $_total_posts = array_sum($_num_posts);
        $detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] );
        if ( !isset( $total_orphans ) )
            $total_orphans = $wpdb->get_var("
                SELECT COUNT( * ) 
                FROM $wpdb->posts 
                WHERE post_type = 'attachment' 
                AND post_author = $current_user->ID 
                AND post_status != 'trash' 
                AND post_parent < 1
            ");
        $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts));
        foreach ( $matches as $type => $reals )
            foreach ( $reals as $real )
                $num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real];
        $class = ( empty($_GET['post_mime_type']) && !$detached && !isset($_GET['status']) ) ? ' class="current"' : '';
        $views['all'] = "<a href='upload.php'$class>" . sprintf( __('All <span class="count">(%s)</span>', 'uploaded files' ), number_format_i18n( $_total_posts )) . '</a>';
        foreach ( $post_mime_types as $mime_type => $label ) {
            $class = '';
            if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) )
                continue;
            if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) )
                $class = ' class="current"';
            if ( !empty( $num_posts[$mime_type] ) )
                $views[$mime_type] = "<a href='upload.php?post_mime_type=$mime_type'$class>" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), $num_posts[$mime_type] ) . '</a>';
        }
        $views['detached'] = '<a href="upload.php?detached=1"' . ( $detached ? ' class="current"' : '' ) . '>' . sprintf( __( 'Unattached <span class="count">(%s)</span>', 'detached files' ), $total_orphans ) . '</a>';
        return $views;
    }
    
  • Hi @rainstorminc

    Because your case is quite specific, I would encourage you to add a filter to the pre_get_posts and edit the ‘wrong’ settings that the events post type plugin is adding.

    I would rather not bloat the core and add potential issues for other users if possible.

    Thanks for understanding and thanks for the bug report.

    Cheers
    E

  • Hi Elliot,

    Thanks for the response!

    Yes, I agree — it’s perfectly reasonable to suspect that post__in would be enough. The conflict occurs with another plugin that handles Event custom post types.

    This events plugin uses the “pre_get_posts” method. During the process of using this method, the plugin will end up adding a tiny piece to the query if it has to do with a post_type that the plugin is responsible for. Ie, your query says “Give me all post types” and then the event plugin says “hey, that query has to do with events — so add on this event-related piece”. The end result is that the query doesn’t return anything because the event piece isn’t appropriate to be added in this case since it’s not really about events.

    I’ll be the first to admit that there’s probably something that could change in the event plugin to avoid this issue. Having said that, my guess is that ACF is more widely supported than the other and therefore, more likely to be updated. Plus, I figured the update actually made sense anyway to restrict the results to certain post_types. Especially, since it was already filtering to certain post_types anyway, it just wasn’t being that specific.

    What do you think?

  • Hi @homax

    So, if you were to now remove the above code, your archive page will load as expected?

    I think there is something fishy going on in your theme in regards to the wp posts loop.

    Perhaps you have a pre_get_posts filter or one of the many other filters in WP / ACF which is modifying the $query.

    It is very easy to accidentally break the global $query in WP and I believe this is what is happening to you.

    Maybe in your code, you are hooking in somewhere and performing a new WP_Query object? If so, make sure you are resetting the query afterwards.

    It may be beneficial to create a new WP install on your local server and just install ACF. Create the same field and edit the twenty12 theme to use this $posts loop. It should work and hopefully give you an idea of where the issue must stem from.

Viewing 25 results - 426 through 450 (of 457 total)