Forum Replies Created

Viewing 15 replies - 1 through 15 (of 36 total)
  • Thread Starter vrandom

    (@vrandom)

    of course, i was brain dead yesterday. Sorry

    Hi @ainsleyclark

    Awesome glad it started working mostly – lol.

    Not sure what could be causing the page number problem.

    I guess start dumping out the vars and checking the math.

    
    // set vars for found_posts, max_posts_count and build the post_order_index
    $found_posts = 0;
    $max_posts_count=0;
    foreach ($page_count_per_post_type as $page_count) {
    
    	// make a total post found for all post_types
    	$found_posts += $page_count[0];
    
    	// max posts - total of posts per type
    	$max_posts_count += $page_count[0];
    
    	// set up post order index
    	$post_order_index[$page_count[1]] = explode(',', $page_count[2]);
    
    }
    
    // set the max pages for the results
    $max_posts_num_pages = ceil( $max_posts_count / ($post_per_posttype * count($post_types)));
    

    Hi @ainsleyclark,

    Sorry, I didn’t open gmail this weekend so i missed your message.

    I looked at the query and it worked in my SQL utility but did not in WordPress.

    I changed the found_post_query_select_addon line:

    
    $found_post_query_select_addon = "post_type_0.grouped_id as one, post_type_1.grouped_id as two, post_type_2.grouped_id as three";
    

    And i got results in WordPress. On my test db the results looked like this.

    
    /home/vagrant/Code/wordpress/wp-content/themes/twentysixteen/page-my-test-page.php:277:
    array (size=3)
      0 => 
        array (size=5)
          0 => string '5' (length=1)
          1 => string 'post1' (length=5)
          2 => string '270,269,268,262,261' (length=19)
          3 => null
          4 => null
      1 => 
        array (size=5)
          0 => string '9' (length=1)
          1 => string 'post2' (length=5)
          2 => null
          3 => string '340,334,291,284,276,275,274,271' (length=31)
          4 => null
      2 => 
        array (size=5)
          0 => string '5' (length=1)
          1 => string 'post3' (length=5)
          2 => null
          3 => null
          4 => string '305,304,303,300,295' (length=19)
    

    That is what we want to see. The original code put rows 2,3 and 4 in to one, removing the null. The reason that its not working for you is that the result is missing the values for the 2, 3, and 4 rows.

    I didn’t see anything wrong in the code. So i’m not sure what to do to troubleshoot the issue.

    What flavor of database server are you using? MySQL? Do you have access to run queries direct on the server, using phpMyAdmin for example.

    You might try making a test page just to test the query parts. Then break the sql down in to parts and run each part to ensure some data is returned.

    Something like this.

    new file saved at WordPress root directory (where the index.php file is), i named my file: test.php

    
    <?php
    // Load the WordPress library.
    require_once( dirname(__FILE__) . '/wp-load.php' );
    
    // Set up the WordPress query.
    wp();
    
    // set up sql parts
    
    // part 1
    $sql_news_part = "select GROUP_CONCAT(id  order by post_date desc, id desc) as grouped_id, post_type from (
    			  SELECT id, post_type, post_date
    			  FROM foe_342fj29x2_posts 
    				inner join foe_342fj29x2_term_relationships on foe_342fj29x2_term_relationships.object_id = id
    				inner join foe_342fj29x2_term_taxonomy on foe_342fj29x2_term_relationships.term_taxonomy_id = foe_342fj29x2_term_taxonomy.term_taxonomy_id
    				inner join foe_342fj29x2_terms on foe_342fj29x2_term_taxonomy.term_id = foe_342fj29x2_terms.term_id
    				where foe_342fj29x2_term_taxonomy.taxonomy = 'category' and foe_342fj29x2_terms.slug = 'marketing-masters'
    			   and post_type in ('news')
    			   and post_status = 'publish'
    			   order by post_date desc, id desc                       
    			  ) d0
    			 GROUP BY d0.post_type";
    
    // part 2
    $sql_exhibitors_part ="select GROUP_CONCAT(id  order by post_date desc, id desc) as grouped_id, post_type from (
    			  SELECT id, post_type, post_date
    			  FROM foe_342fj29x2_posts 
    				inner join foe_342fj29x2_term_relationships on foe_342fj29x2_term_relationships.object_id = id
    				inner join foe_342fj29x2_term_taxonomy on foe_342fj29x2_term_relationships.term_taxonomy_id = foe_342fj29x2_term_taxonomy.term_taxonomy_id
    				inner join foe_342fj29x2_terms on foe_342fj29x2_term_taxonomy.term_id = foe_342fj29x2_terms.term_id
    				where foe_342fj29x2_term_taxonomy.taxonomy = 'category' and foe_342fj29x2_terms.slug = 'marketing-masters'
    			   and post_type in ('exhibitors')
    			   and post_status = 'publish'
    			   order by post_date desc, id desc                       
    			  ) d1
    			 GROUP BY d1.post_type";
    
    // part 3
    $sql_speakers_part = "select GROUP_CONCAT(id  order by post_date desc, id desc) as grouped_id, post_type from (
    			  SELECT id, post_type, post_date
    			  FROM foe_342fj29x2_posts 
    				inner join foe_342fj29x2_term_relationships on foe_342fj29x2_term_relationships.object_id = id
    				inner join foe_342fj29x2_term_taxonomy on foe_342fj29x2_term_relationships.term_taxonomy_id = foe_342fj29x2_term_taxonomy.term_taxonomy_id
    				inner join foe_342fj29x2_terms on foe_342fj29x2_term_taxonomy.term_id = foe_342fj29x2_terms.term_id
    				where foe_342fj29x2_term_taxonomy.taxonomy = 'category' and foe_342fj29x2_terms.slug = 'marketing-masters'
    			   and post_type in ('speakers')
    			   and post_status = 'publish'
    			   order by post_date desc, id desc                       
    			  ) d2
    			 GROUP BY d2.post_type";
    
    // make final sql
    $sql_final = "select count(foe_342fj29x2_posts.id), foe_342fj29x2_posts.post_type, post_type_0.grouped_id as one, post_type_1.grouped_id as two, post_type_2.grouped_id as three from foe_342fj29x2_posts 
    left join 			 
    		($sql_news_part) post_type_0		 
    			 ON foe_342fj29x2_posts.post_type = post_type_0.post_type
    left join 			 
    		($sql_exhibitors_part) post_type_1		 
    			 ON foe_342fj29x2_posts.post_type = post_type_1.post_type
    left join 			 
    		($sql_speakers_part) post_type_2		 
    			 ON foe_342fj29x2_posts.post_type = post_type_2.post_type where foe_342fj29x2_posts.post_type in ('news', 'exhibitors', 'speakers') group by foe_342fj29x2_posts.post_type";
    
    // make sure we have the db access
    global $wpdb;
    
    //----------------------------------------------------------------------------------
    // run query for just the $sql_news_part
    $testresults = $wpdb->get_results($sql_news_part, ARRAY_N);
    
    echo "sql_news_part:<pre>";
    print_r($testresults);
    echo "</pre>";
    
    //----------------------------------------------------------------------------------
    // run query for just the $sql_exhibitors_part
    $testresults = $wpdb->get_results($sql_exhibitors_part, ARRAY_N);
    
    echo "sql_exhibitors_part:<pre>";
    print_r($testresults);
    echo "</pre>";
    
    //----------------------------------------------------------------------------------
    // run query for just the $sql_news_part
    $testresults = $wpdb->get_results($sql_speakers_part, ARRAY_N);
    
    echo "sql_speakers_part:<pre>";
    print_r($testresults);
    echo "</pre>";
    
    // ------
    /*
    Results from each of those three should be something like this :
    
    array (size=1)
      0 => 
        array (size=2)
          0 => string '305,304,303,300,295' (length=19)
          1 => string 'post3' (length=5)
    
    But using 'news', 'exhibitors', or 'speakers' instead of post3
    */
    
    //----------------------------------------------------------------------------------
    // run query for final query
    $testresults = $wpdb->get_results($sql_final, ARRAY_N);
    
    echo "sql_final:<pre>";
    print_r($testresults);
    echo "</pre>";
    
    // these results should be what i posted above with 2,3 and 4 rows.
    

    Give that a try, hopefully you will get data.

    Hi @ainsleyclark

    odd i linked it from the gist and its line 320 there.

    What you have should have worked. Add a dump of the sql, lets see what is looks like.

    
    // base template for sql query
    $sql_template = "select count(foe_342fj29x2_posts.id), foe_342fj29x2_posts.post_type#sql_col# from foe_342fj29x2_posts #join_templates# where foe_342fj29x2_posts.post_type in ('".implode("', '", $post_types)."') group by foe_342fj29x2_posts.post_type";
    
    // Assemble Query
    
    // adds a comma separated list of the post ids that are found in each join statement to the results
    //$found_post_query_select_addon = "CASE " . implode(' ', $selectFoundPostQueryAddon). " ELSE null END as post_ids";
    
    $found_post_query_select_addon = "post_type_0.grouped_id, post_type_1.grouped_id, post_type_2.grouped_id";
    
    $sql_template = str_replace("#sql_col#", ','.$found_post_query_select_addon, $sql_template);
    
    // adds generated joins to query
    $sql_template = str_replace("#join_templates#", implode("\n", $joinTemplate), $sql_template);
    
    echo "<pre>";
    var_dump($sql_template);
    echo "</pre>"
    
    // execute posts build query
    global $wpdb;
    $page_count_per_post_type = $wpdb->get_results($sql_template, ARRAY_N);
    
    // First place to check if we have results
    echo "<pre>";
    var_dump($page_count_per_post_type);
    echo "</pre>"
    

    Hi @ainsleyclark

    Thats odd, it doesn’t look like its using the updated var. Did you place that line after line 320

    The query should have more array values than just 3.

    Hi @ainsleyclark

    Its not generating the post_ids result.

    The $selectFoundPostQueryAddon array part of the query is not working for some reason.

    For testing, try this to make sure there is data.

    above where the pre statement is find the following and comment it out,

    
    // $found_post_query_select_addon = "CASE " . implode(' ', $selectFoundPostQueryAddon). " ELSE null END as post_ids";
    

    make a new line under it

    
    $found_post_query_select_addon = "post_type_0.grouped_id, post_type_1.grouped_id, post_type_2.grouped_id";
    

    then run the page again as see what data you get.

    Hi @ainsleyclark

    Its ok, happens to us all.

    Ok, i noticed a lot of code that didn’t get copied. You were missing the entire rebuilt query part.

    So I went through and made a updated gist using yours as the base. You should be able to just replace your entire page code with the gist copy.

    https://gist.github.com/TerrePorter/fe7b52b4f2e5d8d56ff12dab939ffc4f

    Give this a try and let me know how it goes.

    Ok, I see why the errors occurred.

    First you forgot to update these.

    
    // set up vars
    $post_slug='news'; //$post->post_name;
    $post_types = ['post1', 'post2', 'post3'];
    

    So the first query returned no data which caused the errors.

    To account for the possibility of no data returned from the first query we need to update one line. Wrap the while loop in a if count to make sure we have post_ids_to_fetch.

    
    // if we need more posts to make total wanted on page
    if (count($post_ids_to_fetch)) {
      while (count($post_ids_to_fetch) < (count($post_types) * $post_per_posttype)) {
        ...
      }
    }
    

    Give that a try and let me know how it goes.

    hey @ainsleyclark ,

    Wow that is a lot of errors.

    I would need to see the code to figure out whats happening.

    If you didn’t want to paste it here, you could make a gist (https://gist.github.com/) and share it that way then be able to delete it after we get it figured out.

    Rebuilt code – a whole lot has changed.

    It will:
    – fetch up to $post_per_posttype number of posts for each post type specified in the $post_types array
    – if this result is less than (count($post_types) * $post_per_posttype), then it will attempt to get more posts from the other post types.
    – it will use the $post_types order to get new listings

    Let me know if this works for what your wanting.

    Readable copy here, https://gist.github.com/TerrePorter/110facd34376b8ab171890a8bb247081

    
    <?php
        // hack to overwrite the max_num_queries var
    		class WP_Query_CustomSQL extends WP_Query
    		{
    
    			function get_posts() {
    			    $posts = parent::get_posts();
    
    			    // overwrite max_num_pages settings if set
    			    $q = &$this->query_vars;
    
    			    if (isset($q['max_num_pages'])) {
    			        $this->max_num_pages = $q['max_num_pages'];
    			    }
    
    			    return $posts;
                }
    		}
    
    		function paginate_links_with_provided_wpquery( $args = '', $wp_query) {
    			global $wp_rewrite;
    
    			// Setting up default values based on the current URL.
    			$pagenum_link = html_entity_decode( get_pagenum_link() );
    			$url_parts    = explode( '?', $pagenum_link );
    
    			// Get max pages and current page out of the current query, if available.
    			$total   = isset( $wp_query->max_num_pages ) ? $wp_query->max_num_pages : 1;
    			$current = get_query_var( 'paged' ) ? intval( get_query_var( 'paged' ) ) : 1;
    
    			// Append the format placeholder to the base URL.
    			$pagenum_link = trailingslashit( $url_parts[0] ) . '%_%';
    
    			// URL base depends on permalink settings.
    			$format  = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
    			$format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';
    
    			$defaults = array(
    				'base'               => $pagenum_link, // http://example.com/all_posts.php%_% : %_% is replaced by format (below)
    				'format'             => $format, // ?page=%#% : %#% is replaced by the page number
    				'total'              => $total,
    				'current'            => $current,
    				'aria_current'       => 'page',
    				'show_all'           => false,
    				'prev_next'          => true,
    				'prev_text'          => __( '&laquo; Previous' ),
    				'next_text'          => __( 'Next &raquo;' ),
    				'end_size'           => 1,
    				'mid_size'           => 2,
    				'type'               => 'plain',
    				'add_args'           => array(), // array of query args to add
    				'add_fragment'       => '',
    				'before_page_number' => '',
    				'after_page_number'  => '',
    				'hide_page_numbers'  => false
    			);
    
    			$args = wp_parse_args( $args, $defaults );
    
    			if ( ! is_array( $args['add_args'] ) ) {
    				$args['add_args'] = array();
    			}
    
    			// Merge additional query vars found in the original URL into 'add_args' array.
    			if ( isset( $url_parts[1] ) ) {
    				// Find the format argument.
    				$format = explode( '?', str_replace( '%_%', $args['format'], $args['base'] ) );
    				$format_query = isset( $format[1] ) ? $format[1] : '';
    				wp_parse_str( $format_query, $format_args );
    
    				// Find the query args of the requested URL.
    				wp_parse_str( $url_parts[1], $url_query_args );
    
    				// Remove the format argument from the array of query arguments, to avoid overwriting custom format.
    				foreach ( $format_args as $format_arg => $format_arg_value ) {
    					unset( $url_query_args[ $format_arg ] );
    				}
    
    				$args['add_args'] = array_merge( $args['add_args'], urlencode_deep( $url_query_args ) );
    			}
    
    			// Who knows what else people pass in $args
    			$total = (int) $args['total'];
    			if ( $total < 2 ) {
    				return;
    			}
    			$current  = (int) $args['current'];
    			$end_size = (int) $args['end_size']; // Out of bounds?  Make it the default.
    			if ( $end_size < 1 ) {
    				$end_size = 1;
    			}
    			$mid_size = (int) $args['mid_size'];
    			if ( $mid_size < 0 ) {
    				$mid_size = 2;
    			}
    			$add_args = $args['add_args'];
    			$r = '';
    			$page_links = array();
    			$dots = false;
    
    			if ( $args['prev_next'] && $current && 1 < $current ) :
    				$link = str_replace( '%_%', 2 == $current ? '' : $args['format'], $args['base'] );
    				$link = str_replace( '%#%', $current - 1, $link );
    				if ( $add_args )
    					$link = add_query_arg( $add_args, $link );
    				$link .= $args['add_fragment'];
    
    				/**
    				 * Filters the paginated links for the given archive pages.
    				 *
    				 * @since 3.0.0
    				 *
    				 * @param string $link The paginated link URL.
    				 */
    				$page_links[] = '<a class="prev page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['prev_text'] . '</a>';
    			endif;
    			if (! $args['hide_page_numbers']) {
                    for ( $n = 1; $n <= $total; $n++ ) :
                        if ( $n == $current ) :
                            $page_links[] = "<span aria-current='" . esc_attr( $args['aria_current'] ) . "' class='page-numbers current'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . "</span>";
                            $dots = true;
                        else :
                            if ( $args['show_all'] || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) :
                                $link = str_replace( '%_%', 1 == $n ? '' : $args['format'], $args['base'] );
                                $link = str_replace( '%#%', $n, $link );
                                if ( $add_args )
                                    $link = add_query_arg( $add_args, $link );
                                $link .= $args['add_fragment'];
    
                                /** This filter is documented in wp-includes/general-template.php */
                                $page_links[] = "<a class='page-numbers' href='" . esc_url( apply_filters( 'paginate_links', $link ) ) . "'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . "</a>";
                                $dots = true;
                            elseif ( $dots && ! $args['show_all'] ) :
                                $page_links[] = '<span class="page-numbers dots">' . __( '&hellip;' ) . '</span>';
                                $dots = false;
                            endif;
                        endif;
                    endfor;
    			}
    			if ( $args['prev_next'] && $current && $current < $total ) :
    				$link = str_replace( '%_%', $args['format'], $args['base'] );
    				$link = str_replace( '%#%', $current + 1, $link );
    				if ( $add_args )
    					$link = add_query_arg( $add_args, $link );
    				$link .= $args['add_fragment'];
    
    				/** This filter is documented in wp-includes/general-template.php */
    				$page_links[] = '<a class="next page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['next_text'] . '</a>';
    			endif;
    			switch ( $args['type'] ) {
    				case 'array' :
    					return $page_links;
    
    				case 'list' :
    					$r .= "<ul class='page-numbers'>\n\t<li>";
    					$r .= join("</li>\n\t<li>", $page_links);
    					$r .= "</li>\n</ul>\n";
    					break;
    
    				default :
    					$r = join("\n", $page_links);
    					break;
    			}
    			return $r;
    		}
            // ----------------------------------------------------
    
            // set up vars
    		$post_slug='news'; //$post->post_name;
            $post_types = ['post1', 'post2', 'post3'];
    
            // number of post to show per each post_type
            $post_per_posttype = 2;
    
            // to keep the last post id that is being displayed on the page
            $last_post_id_by_type= [];
    
            // keeps the display of posts order
            $post_order_index= [];
    
            // get the current page number
            $current_page_number = get_query_var('paged', 1);
            // if 0, then we are on page 1
            if ($current_page_number==0) { $current_page_number = 1; }
    
            // check if we have sql_offset info for this page load
            $transient_key = implode('-', $post_types).'_sqloffset_page';
            if ( false === ( $sql_offset = get_transient( $transient_key . $current_page_number) ) ) {
                // no valid transient set
                foreach ($post_types as $post_type_key => $post_type) {
                    $sql_offset[$post_type] = 0;
                }
            }
    
    		// Make SQL Parts
            $joinTemplate = [];
            $whereTemplate = [];
    		foreach ($post_types as $post_type_key => $post_type) {
    
    		    $joinTemplate[] = "left join 			 
                    (select GROUP_CONCAT(id  order by post_date desc, id desc) as grouped_id, post_type from (
                          SELECT id, post_type, post_date
                          FROM wp_posts 
                            inner join wp_term_relationships on wp_term_relationships.object_id = id
                            inner join wp_term_taxonomy on wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
                            inner join wp_terms on wp_term_taxonomy.term_id = wp_terms.term_id
                            where wp_term_taxonomy.taxonomy = 'category' and wp_terms.slug = '$post_slug'
                           and post_type in ('$post_type')
                           and post_status = 'publish'
                           order by post_date desc, id desc                       
                          ) d$post_type_key
                         GROUP BY d$post_type_key.post_type) post_type_$post_type_key		 
                         ON wp_posts.post_type = post_type_$post_type_key.post_type";
    
    		    $selectFoundPostQueryAddon[] = "WHEN wp_posts.post_type = '$post_type' THEN post_type_$post_type_key.grouped_id";
    		}
    
    		// base tempate for sql query
    		$sql_template = "select count(wp_posts.id), wp_posts.post_type#sql_col# from wp_posts #join_templates# where wp_posts.post_type in ('".implode("', '", $post_types)."') group by wp_posts.post_type";
    
            // Assemble Query
    
    		// adds a comma seperated list of the post ids that are found in each join statement to the results
    		$found_post_query_select_addon = "CASE " . implode(' ', $selectFoundPostQueryAddon). " ELSE null END as post_ids";
    		$sql_template = str_replace("#sql_col#", ','.$found_post_query_select_addon, $sql_template);
    
    		// adds generated joins to query
    		$sql_template = str_replace("#join_templates#", implode("\n", $joinTemplate), $sql_template);
    
            // execute posts build query
    		global $wpdb;
    		$page_count_per_post_type = $wpdb->get_results($sql_template, ARRAY_N);
    
            // set vars for found_posts, max_posts_count and build the post_order_index
    		$found_posts = 0;
    		$max_posts_count=0;
    		foreach ($page_count_per_post_type as $page_count) {
    
    		    // make a total post found for all post_types
    		    $found_posts += $page_count[0];
    
    		    // max posts - total of posts per type
    		    $max_posts_count += $page_count[0];
    
    		    // set up post order index
    		    $post_order_index[$page_count[1]] = explode(',', $page_count[2]);
    
    		}
    
    		// set the max pages for the results
    		$max_posts_num_pages =  ceil( $max_posts_count / ($post_per_posttype * count($post_types)));
    
            // get base post ids to show using the normal post_per_posttype
    		$no_more_post_for_post_type=[];
    		$post_ids_to_fetch = [];
    		foreach ($post_order_index as $k => $v) {
    
                // using the sql_offset for this post type, get the next x results from the post_order_index
                $t = array_slice($v, $sql_offset[$k], $post_per_posttype);
    
                // if number available is less than or equal to the offset+post_per_posttype, then there are no more post to fetch for this type
                if (count($v) <=  ($sql_offset[$k] + $post_per_posttype)) {
                    $no_more_post_for_post_type[] = $k;
                }
    
                // keep a growing list of post ids
    		    $post_ids_to_fetch = $post_ids_to_fetch + array_combine($t, array_pad([], count($t), $k));
    		}
    
    		// if we need more posts to make total wanted on page
    	    while (count($post_ids_to_fetch) < (count($post_types) * $post_per_posttype)) {
    
    	        // get current count of postids to fetch by post type
    		    $post_ids_to_fetch_count_per_type = array_count_values($post_ids_to_fetch);
    
    		    // remove any post_types that do not have any more posts
    		    $post_types_with_more_posts = [];
    		    foreach ($post_types as $k => $v) {
    		        if (!in_array($v, $no_more_post_for_post_type)) {
    		            $post_types_with_more_posts[] =$v;
    		        } else {
    		            unset($post_ids_to_fetch_count_per_type[$v]);
    		        }
    		    }
    
    		    // if have more posts
    		    if (count($post_types_with_more_posts)) {
    
    		        // get the post type with the lowest count from the number of ids in $post_ids_to_fetch
                    $fetch_more_from_post_type = array_search(min($post_ids_to_fetch_count_per_type), $post_ids_to_fetch_count_per_type);
    
                    // get the next post id from the post order index
                    $t = array_slice($post_order_index[$fetch_more_from_post_type], $sql_offset[$fetch_more_from_post_type] + $post_ids_to_fetch_count_per_type[$fetch_more_from_post_type], 1);
    
                    // check if this is the last id available
                    if ((count($post_order_index[$fetch_more_from_post_type]) <=  ($sql_offset[$fetch_more_from_post_type] + $post_ids_to_fetch_count_per_type[$fetch_more_from_post_type] + 1))) {
                        $no_more_post_for_post_type[] = $fetch_more_from_post_type;
                    }
    
                    $post_ids_to_fetch = $post_ids_to_fetch + array_combine($t, array_pad([], count($t), $fetch_more_from_post_type));
    
    		    } else {
    		        //There are no more posts to fetch, stop trying to get more
    		        break; // exit the while loop
    		    }
    
    		}
    
    		// get current count of postids to fetch by post type
    		$post_ids_to_fetch_count_per_type = array_count_values($post_ids_to_fetch);
    
    		// fetch the display posts query
    		$loop = new WP_Query_CustomSQL(
    		        array(
    		                'post_type'      => $post_types,
                            'post__in'      => array_keys($post_ids_to_fetch),
    		                'max_num_pages' => $max_posts_num_pages
    		             )
    		        );
    
     		// put the post in the order of the post_types array
    		if ($loop->have_posts()) {
    
    		    // make posts index by post_type
    		    $tmpPosts = [];
                foreach ($loop->posts as $k => $v) {
                    $tmpPosts[get_post_type( $v->ID )][$v->ID] = $v;
    
                    // update the offset to add in this post to the count
                    $sql_offset[get_post_type( $v->ID )] += 1;
                }
    
                // assemble new ordered posts
                $finPosts = [];
                foreach ($post_types as $k => $v) {
                    if (isset($tmpPosts[$v])) {
    
                        // reorder based on the sql result order
                        foreach ($post_order_index[$v] as $k1 => $v1) {
                            if (isset($tmpPosts[$v][$v1])) {
    
                                // make an array of posts grouping them in the post_types order
                                $finPosts[] = $tmpPosts[$v][$v1];
    
                                // set last post id for each type
    		                    $last_post_id_by_type[$v] = (int) $v1;
                            }
                        }
                    }
                }
    
                // update the $loop with the new ordered posts
                $loop->posts = $finPosts;
    
                // save the sql offset data for the next page view
                if ($current_page_number + 1 <= $max_posts_num_pages) {
                    set_transient($transient_key . ($current_page_number + 1), $sql_offset);
                }
    		}
    
    		// begin display code
    
    		$speakerCounter = 0;
    		$exhibitorCounter = 0;
    		$columnwidth = 'col-lg-6';
    		if ( $loop->have_posts() ) :
    			while ( $loop->have_posts() ) : $loop->the_post();
    
    		        // get post type of current post
    				$post_type = get_post_type( $post->ID );
    
    				/// do something with the last post of each post_type being displayed on the page
                    if ($last_post_id_by_type[$post_type] == $post->ID) {
                          //do something
                          echo "LAST POST";
                    }
    
    				if ($post_type == 'post1' && $newsCounter < $post_ids_to_fetch_count_per_type['post1']) {
                        $newsCounter++;
                        //require( locate_template ('blocks/content-newsrow.php'));
                        echo $post->ID . '] ' . $post_type . ' - '  .  get_permalink($post->ID)  . "<BR>";
                    }
                    if ($post_type == 'post2' && $exhibitorCounter < $post_ids_to_fetch_count_per_type['post2']) {
                        if ($exhibitorCounter == 0) {
                            echo '<div class="row"><div class="col-12 mb-2 mb-lg-3">'; ?>
                            <span class="contentbrands__title type__weight--medium">Exhibitors for <?php echo $contentbrand; ?>:</span>
                            </div></div>
                            <?php echo '<div class="row">'; ?>
                        <?php }
                            $exhibitorCounter++;
                            //require( locate_template ('blocks/content-exhibitor.php'));
                            echo $post->ID . '] ' . $post_type . ' - '  .  get_permalink($post->ID)  . "<BR>";
                        if ($exhibitorCounter == 2) {echo '</div>';}
                    }
                    if ($post_type == 'post3' && $speakerCounter < $post_ids_to_fetch_count_per_type['post3']) {
                        if ($speakerCounter == 0) {
                            echo '<div class="row"><div class="col-12 mb-2 mb-lg-3">'; ?>
                            <span class="contentbrands__title type__weight--medium">Experts for <?php echo $contentbrand; ?>:</span>
                            </div></div>
                            <?php echo '<div class="row">'; ?>
                        <?php }
                            $speakerCounter++;
                            //require( locate_template ('blocks/content-speaker.php'));
                            echo $post->ID . '] ' . $post_type . ' - '  .  get_permalink($post->ID)  . "<BR>";
                        if ($speakerCounter == 1) {echo '</div>';}
                    }
    
    			endwhile;
    
    			// Previous/next page navigation.
    			$args = array(
    				'prev_text'          => __( 'Previous page', 'twentysixteen' ),
    				'next_text'          => __( 'Next page', 'twentysixteen' ),
    				'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>',
    				'screen_reader_text' => __( 'Posts navigation' ),
    				'type'               => 'plain',
    				'hide_page_numbers'          => true
    			);
    
    			// Set up paginated links.
    			$links = paginate_links_with_provided_wpquery( $args , $loop);
    
    			if ( $links ) {
    				echo _navigation_markup( $links, 'pagination', $args['screen_reader_text'] );
    			}
    			?>
    
    			<?php
    		else :
    			echo '<h3>No News</h3>';
    		endif;
    		wp_reset_postdata();
    
    

    Humm, not sure why it would be calculating the pages off by one. db count sql are usually accurate

    
    $page_count_per_post_type = $wpdb->get_results($sqlQuerys['found_post_query'], ARRAY_N);
    
    // add these lines
    echo "<pre>";
            var_dump($page_count_per_post_type[0][1] . ': ' . ceil( $page_count_per_post_type[0][0] / 2 ));
            var_dump($page_count_per_post_type[1][1] . ': ' . ceil( $page_count_per_post_type[1][0] / 2 ));
            var_dump($page_count_per_post_type[2][1] . ': ' . ceil( $page_count_per_post_type[2][0] / 2 ));
            echo "</pre>";
    

    this should dump out the calculated pages per post type. The highest one should be the number of pages displayed. If its not then someplace in the code is changing it.

    For your second question.

    The db query is build to only fetch 2 per post type. I dont see a way to do what you ask, as it would mess up the query results.

    for example, if a post type is empty, then grab more listings from another post type.

    I have been pondering.

    A walk through:

    page 1, it loads (2 news, 2 exhibitors, 2 speakers)
    page 2, it loads (2 news, 1 exhibitors, 2 speakers)
    — we detect that there are not 2 in each post type.
    — we set a tmp var holding the types that are below 2 posts (exhibitors)
    — (#a) check if holding var has all three types
    — if yes, then no more posts to get, goto #b, if no continue next line
    — find lowest page count of post types, if two are the same use the order
    — (news, exhibitors, speakers)
    — in this case, news and speakers have 2 post, exhibitors is excluded
    — news, speakers – in use order, news is selected.
    — we check the $page_count_per_post_type post id list
    — extract the next post id from the list
    — (using sql_offset for type and current posts used count, to find it)
    — if no post id found, then set type in holding var and goto #a
    — if post id is last post and displayed, then set type in holding var, goto #a
    — add the found post id to a “need_to_fetch” var for later
    — add one to the news count in page_count_per_post_type
    — recheck total, have 6 posts to display?
    — no, then go back to #a and repeat for the next available post type
    — #b, if have need_to_fetch post ids, continue next line, if not, goto #c
    — proceed to fetching the posts in the “need_to_fetch” list
    — add results to the original results
    — update custom sql_offset for each type
    — (using posts used this page load + previous sql_offset for each type)
    — store sql_offset in session as we need to send to next page
    — #c
    — done with this part, continue with rest of code

    In walk through, we end up with (3 news, 1 exhibitors, 2 speakers) on page 2.

    At first i didnt think it was possible. Since it would mess up the base sql as it has an order that it follows.

    After that walk thought. I think it could be done. This would revert the pagination to using the total number of posts (add post count from each post type together for total) in the page calculation. It would also prevent the page from only displaying multiple pages of less than 6 on the page.

    We would have to keep a custom offset for each post type in order to maintain what has been used and what has not. This should allow for all pages to have 6 results (maybe not last page) using whatever counts per type needed to get 6 results.

    If this sounds good, i will see if i can get some time to make the code adjustments.

    Yes that code block is in the paginate_links_with_provided_wpquery function.

    Then down in the main code, update the settings (add hide_page_numbers to the array) for the paginate function call.

    
    // Previous/next page navigation.
    $args = array(
    	'prev_text' => __( 'Previous page', 'twentysixteen' ),
    	'next_text'          => __( 'Next page', 'twentysixteen' ),
    	'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>',
    	'screen_reader_text' => __( 'Posts navigation' ),
    	'type'               => 'plain',
    	'hide_page_numbers'          => true
    );
    

    Ok, to hide the page numbers. Since we are using a custom paginate_links function we can add a new option.

    in the function, paginate_links_with_provided_wpquery, add the wrapping if (if (! $args[‘hide_page_numbers’]) {) statement. The rest is just for you to be able to find where.

    
    if (! $args['hide_page_numbers']) {
                    for ( $n = 1; $n <= $total; $n++ ) :
                        if ( $n == $current ) :
                            $page_links[] = "<span aria-current='" . esc_attr( $args['aria_current'] ) . "' class='page-numbers current'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . "</span>";
                            $dots = true;
                        else :
                            if ( $args['show_all'] || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) :
                                $link = str_replace( '%_%', 1 == $n ? '' : $args['format'], $args['base'] );
                                $link = str_replace( '%#%', $n, $link );
                                if ( $add_args )
                                    $link = add_query_arg( $add_args, $link );
                                $link .= $args['add_fragment'];
    
                                /** This filter is documented in wp-includes/general-template.php */
                                $page_links[] = "<a class='page-numbers' href='" . esc_url( apply_filters( 'paginate_links', $link ) ) . "'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . "</a>";
                                $dots = true;
                            elseif ( $dots && ! $args['show_all'] ) :
                                $page_links[] = '<span class="page-numbers dots">' . __( '&hellip;' ) . '</span>';
                                $dots = false;
                            endif;
                        endif;
                    endfor;
    			}
    

    “And count of these and manually pass it into where the pagination is counted?”

    If you get a count of the posts, it does not calculate the correct number of pages in order to show all the results.

    I will try to explain the page counting. For example, we have the following

    news, 5 posts
    speakers, 8 posts
    exhibitors, 6 posts

    if we add that up, we get 19 posts, now if we calculate the number of pages, ceil( total posts / number per page )

    So that is, ceil( 19 / 6 ), which is 3 – so 3 pages

    But since we are showing 2 per post type to total 6, it does not take in to account if we have more of one post type than another to show.

    If we get the number of pages needed to show all the results for each post type

    news, 5 posts – need 3 pages at 2 per page to display results
    speakers, 8 posts – need 4 pages at 2 per page to display results
    exhibitors, 6 posts – need 3 pages at 2 per page to display results

    So if we go with the total 19 posts at 6 per page it said we only needed 3 pages, but speakers needs 4. So the speakers would lose 2 posts as it needed one more page to display all its results.

    Hope that makes sense.

    ok, i see what is happening. Odd that it didnt happen on my dev site but who knows why.

    After the second query, there is some code that reorders the $loop->post as it was not grouping the post type next to each other and that caused some weird display issues.

    I have updated the code to use the sql order to rebuild the array.

    
    // get the largest page count on a page
    		$largest_page_count_per_post_type = 0;
    		$found_posts = 0;
    		$last_post_id_by_type= [];
    		$post_order_index= [];
    		foreach ($page_count_per_post_type as $page_count) {
    		    $largest_page_count_per_post_type = ($page_count[0] > $largest_page_count_per_post_type)? $page_count[0]:$largest_page_count_per_post_type;
    		    $found_posts += $page_count[0];
    
    		    // set up post order index
    		    $post_order_index[$page_count[1]] = explode(',', $page_count[2]);
    
    		    // get last post id for each type
    		    $last_post_id_by_type[$page_count[1]] = (int) end($post_order_index[$page_count[1]]);
    
    		}
    

    then down the page,

    
    // put the post in the order of the post_types array
    		if ($loop->have_posts()) {
    
    		    // make posts index by post_type
    		    $tmpPosts = [];
                foreach ($loop->posts as $k => $v) {
                    $tmpPosts[get_post_type( $v->ID )][$v->ID] = $v;
                }
    
                // assemble new ordered posts
                $finPosts = [];
                foreach ($post_types as $k => $v) {
                    if (isset($tmpPosts[$v])) {
                        // reorder based on the sql result order
                        foreach ($post_order_index[$v] as $k1 => $v1) {
                            if (isset($tmpPosts[$v][$v1])) {
                                $finPosts[] = $tmpPosts[$v][$v1];
                            }
                        }
                    }
                }
    
                // update the $loop with the new ordered posts
                $loop->posts = $finPosts;
    		}
    

    “The last post is always for the very last post, regardless of the page.”

    I thought that was what you wanted, but i think you want the last post of each type for the current page.

    Remove the $last_post_id_by_type from the $page_count_per_post_type foreach

    
    		    // get last post id for each type
    		    $last_post_id_by_type[$page_count[1]] = (int) end($post_order_index[$page_count[1]]);		
    

    Update the “// assemble new ordered posts” code from above

    
     // assemble new ordered posts
                $finPosts = [];
                foreach ($post_types as $k => $v) {
                    if (isset($tmpPosts[$v])) {
    
                        // reorder based on the sql result order
                        foreach ($post_order_index[$v] as $k1 => $v1) {
                            if (isset($tmpPosts[$v][$v1])) {
                                $finPosts[] = $tmpPosts[$v][$v1];
    
                                // set last post id for each type
    		            $last_post_id_by_type[$v] = (int) $v1;
                            }
                        }
                    }
                }
    

    The last_post_id_by_type[post_type] should now contain the last post id from the current page.

    • This reply was modified 7 years, 3 months ago by vrandom. Reason: typo-o

    Humm,

    I assume your talking about the $last_post_id_by_type[$post_type]

    
    foreach ($page_count_per_post_type as $page_count) { ... }
    // after for each add this 
    
    echo "<pre>";
    var_dump($last_post_id_by_type);
    echo "<pre>";
    

    It should return an array.

    
    array(3) {
      ["exhibitors"]=>
      int(52)
      ["news"]=>
      int(343)
      ["speakers"]=>
      int(32)
    }
    

    for debug at the conditional, lets show the last id for each post type. And verify what the post type is returning.

    
    echo '<h1>' .post_type . - . .$post->ID. '</h1>';
    if (isset($last_post_id_by_type[$post_type])) {
     echo "<h1>{$last_post_id_by_type[$post_type]}</h1>";
    }
    

    Another thing to look at is the post->id as you got to each page. It should match the order in the $page_count in the for each.

    
    array(3) {
      [0]=>
      array(3) {
        [0]=>
        string(2) "69"
        [1]=>
        string(10) "exhibitors"
        [2]=>
        string(10) "175,121,52"
      }
      [1]=>
      array(3) {
        [0]=>
        string(2) "31"
        [1]=>
        string(4) "news"
        [2]=>
        string(15) "398,397,392,343"
      }
      [2]=>
      array(3) {
        [0]=>
        string(2) "30"
        [1]=>
        string(8) "speakers"
        [2]=>
        string(2) "32"
      }
    }
    

    So on page 1, the page type exhibitors should list out post id 175 and 121. On page 2, it should only show post id 52 (which is the also the last post id)

    Unless there is something changing the order by it should be consistent.

Viewing 15 replies - 1 through 15 (of 36 total)