0

I have following functions ...

function ajax_sortposts() {
    global $wp_query;
    $sorting_order = $_POST['sorting_order'];

    if ( $sorting_order == 'Latest' ) {
        remove_action( 'pre_get_posts', 'query_get_posts_by_views' );
        wp_reset_postdata();
    }
    else {
        add_action( 'pre_get_posts', 'query_get_posts_by_views' );
    }

    get_content();

    die;
} 

function get_content () {
    global $wp_query;
    wp(); 
?>
    <div id="post-wrapper" class="grid-wrapper">
        <?php
            if ( have_posts() ) :
                echo '<div class="gallery-wrapper">';
                while ( have_posts() ) : the_post();
                    if ( 'one-column' === get_option( 'baseline_customizer_post_style', 'one-column' ) ) {
                        get_template_part( 'template-parts/content' );
                    } else {
                        get_template_part( 'template-parts/content-grid-item' );
                    }
                endwhile;

                echo '</div>';
            else :
                get_template_part( 'template-parts/content-none' );
            endif;

            if (  $wp_query->max_num_pages > 1 )
                echo '<div class="loadmore_posts">More posts</div>';
        ?>
    </div>
<?php 
}

function query_get_posts_by_views( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set('post_type', 'post');
        $query->set('posts_per_page', get_option('posts_per_page'));
        $query->set('paged', 1);
        $query->set('post_status', 'publish');
        $query->set('ignore_sticky_posts', true);
        $query->set('tag__not_in', array(14)); 
        $query->set('order', 'DESC');
        $query->set('meta_key', 'link_click_counter');
        $query->set('orderby', 'meta_value_num');
        $query->set('date_query', 
            [    [
                'column' => 'post_date_gmt',
                'after'  => '130 days ago',
            ]    ] 
        );

        return ($query);
    }
}

On click I want to change order of posts on home page by number of post views or return order to default. It is all working fine except remove_action ('pre_get_posts' does not return to original query (it duplicates some posts). What am I doing wrong?

Ajax function:

    jQuery( document ).on( 'click', '[class*=sortingMenu]', function() {
  var sorting_order = jQuery(this).attr('sorting_order');
  jQuery.ajax({
    url : ajaxposts.ajax_posts_url,
    type : 'post',
    data : {
        action : 'sortposts',
        sorting_order : sorting_order
    },
    beforeSend:function( xhr ){
        document.getElementById("sortingLoader").style.visibility = "visible";


    },
    success : function( response ) {

        if (sorting_order == "Latest") {
            document.getElementById("Latest").classList.add('selectedSort');
            document.getElementById("MostViewed").classList.remove('selectedSort');
        }
        else {
            document.getElementById("MostViewed").classList.add('selectedSort');
            document.getElementById("Latest").classList.remove('selectedSort');
        }           

        jQuery('#post-wrapper').remove();
        jQuery('.pagination').remove();
        jQuery('#main').append(response);
        loadmore_posts_params.current_page = 1;

        // Fade in the images as they load
        function fade_images() {
        $('.gallery-wrapper .gallery-thumb').each(function(i) {
            var row = $(this);
            setTimeout(function() {
                row.addClass('fadeInUp');
            }, 90*i)
        });
        }

        // Masonry blocks
        var $blocks = $('.two-column .gallery-wrapper,.three-column .gallery-wrapper');

        $blocks.imagesLoaded( function() {
            $blocks.masonry({
            itemSelector: 'body:not(.one-column) .post',
            transitionDuration: 0
        });

        // Fade blocks in after images are ready
        fade_images();
        });

        document.getElementById("sortingLoader").style.visibility = "hidden";
    },
    error: function () {
        document.getElementById("sortingLoader").style.visibility = "hidden";
    }     
});

return false;

})

Here are the options link:

   function sorting_menu() { ?>

    href="javascript:void(0)" sorting_order="Latest" id="Latest" class="sortingMenu selectedSort">Latest</a>
    &ensp;
    href="javascript:void(0)" sorting_order="MostViewed" id="MostViewed" class="sortingMenu">Most viewed</a>


  } 
  • And what do you do with the result of that AJAX function? Do you add that action anywhere else in your code? And where does the global $wp_query comes from in an AJAX call? How do you set it? – Krzysiek Dróżdż Jun 5 '18 at 6:44
  • @Krzysiek, I have added ajax function code in question above. – Goran Džepina Jun 5 '18 at 8:47
  • OK, so I have no idea how your code does anything - it's some magic, that it even works right now ;) Let me prepare the answer – Krzysiek Dróżdż Jun 5 '18 at 8:50
  • Options links included. Is that what you mean? :) – Goran Džepina Jun 5 '18 at 9:01
0

OK, so first of all - AJAX requests are separate, so you don't have to remove_action if you haven't added it earlier...

And to be honest, I don't really get your code - you modify the global wp_query object, but it's really not so clear how and why is there any query created during AJAX call - WP processes these requests in a different way... Saying this, here's the code that should work... (it doesn't need any changes in your JS, so I'm posting only PHP code)

function ajax_sortposts() {
    $sorting_order = $_POST['sorting_order'];

    // we don't use any global $wp_query, since no global $wp_query is created during AJAX calls
    // instead we create our own WP_Query instance - so we don't need to use pre_get_posts
    $posts_query = new WP_Query( array(
        'post_type' => 'post',
        'posts_per_page', get_option('posts_per_page'),
        'paged' => 1,
        'post_status' => 'publish',
        'ignore_sticky_posts' => true,
        'tag__not_in' => array(14),
        'order' => 'DESC',
        'date_query' => array(
            array(
                'column' => 'post_date_gmt',
                'after'  => '130 days ago',
            )
        )
    ) );
    if ( 'MostViewed' == $sorting_order ) {
        $posts_query['meta_key'] = 'link_click_counter';
        $posts_query['orderby'] = 'meta_value_num';
    }

    get_content( $posts_query );

    die;
} 

function get_content ( $query ) {
    // again we shouldn't use global $wp_query in here
    // and certainly we SHOULDN'T call wp() function at all...
?>
    <div id="post-wrapper" class="grid-wrapper">
        <?php
            if ( $query->have_posts() ) :
                echo '<div class="gallery-wrapper">';
                while ( $query->have_posts() ) : $query->the_post();
                    if ( 'one-column' === get_option( 'baseline_customizer_post_style', 'one-column' ) ) {
                        get_template_part( 'template-parts/content' );
                    } else {
                        get_template_part( 'template-parts/content-grid-item' );
                    }
                endwhile;

                echo '</div>';
            else :
                get_template_part( 'template-parts/content-none' );
            endif;

            if (  $query->max_num_pages > 1 )
                echo '<div class="loadmore_posts">More posts</div>';
        ?>
    </div>
<?php 
}
  • First of all thank you for trying to help. Maybe I wans't clear on my idea. My home page is multi post page, in header of page I have added two links (Latest and Most Viewed). This links call ajax function i .js file. Ajax then calls "ajax_sort_posts" in php wich applies pre_get_posts and returns new content that is refreshed by ajax. This part is working fine. Problem is when I click latest again and want to remove pre_get_posts, my query dosen't return to original state. Hope I was more clear this time. – Goran Džepina Jun 5 '18 at 9:30
  • I understand what you’re trymiga to achieve, but your code is a mess. You can’t call wp() or hope that WP will magically create global wp_query by itself... AJAX requests are processed in a different way so you should create your own query in you AJAX callback function. – Krzysiek Dróżdż Jun 5 '18 at 9:33
  • Ok, I understand. This can't be done this way. I was thinking that I could do it because of problems with pagination if I create separte query. – Goran Džepina Jun 5 '18 at 9:47
  • @GoranDžepina It dań be done using AJAX and it can be done in a simillar way - just not with your code because it’s a magic that it does anything at all ;) Take a look at my answer - this is the code that will be a good starting point - you can easily fiddle with the query that I’ve put in there... – Krzysiek Dróżdż Jun 5 '18 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.