• When

    $in_same_term = true

    when using the get_next_post and get_previous_post functions, and the current post has several parent categories and several child catgeories:

    – will the function pick the next/previous post only from the current posts parent categories or will it also consider child categories?

    – if the post has several categories, let’s say: first, second and third category (both parent and child categories), will it choose a post from all 3 categories, or only from the first?

    And if the current post has categories A and B, then will an other post that has the categories A and B have priority in the next/prev choice, even if its publish date falls further away than let’s say an other post, that has categories A and C?

    And is there any difference in the choices of the functions in comparison, when using get_next_post & get_previous_post, get_adjacent_post and get_{$adjacent}_post_where ?

Viewing 15 replies - 16 through 30 (of 63 total)
  • Thread Starter berry metal

    (@erikalleman)

    If get_the_category(); returns an array, then the best is to compare the arrays instead of individual terms. If the 2 arrays match, then it’s a total match, no matter how many terms are there.

    Could we do something like

    $arraysAreEqual = ($a == $b);, save the current post terms in $a and all other posts terms in $b, one at a time, and after every saving, match them?

    Thread Starter berry metal

    (@erikalleman)

    or is it possible to use array_diff=0 ?

    Thread Starter berry metal

    (@erikalleman)

    So we have to get the term arrays for all posts and then loop through all of the arrays until we find a perfect match, where all terms match. Is that right?

    Thread Starter berry metal

    (@erikalleman)

    I think the easiest is to modify my theme code via the child theme, so that I don’t have to re-make the styles for a new custom shortcode, and it will be perhaps more integrated in my theme?

    There is a next-prev.php in my theme, and here is the relevant code:

    // Check if post has terms if so then show next/prev from the same_cat
    if ( get_theme_mod( 'next_prev_in_same_term', true  ) ) {
    	$has_terms = themeprefix_post_has_terms( get_the_ID() );
    	$same_cat  = $has_terms;
    } else {
    	$same_cat = false;
    }
    $same_cat = apply_filters( 'themeprefix_next_prev_in_same_term', $same_cat, $post_type );
    
    $has_terms = $same_cat ? $has_terms : false; // Added check for filter

    This is what I need to modify, so that it will find matches that have the exact same array of categories, be that only 1 or several.

    • This reply was modified 3 years, 7 months ago by berry metal.
    • This reply was modified 3 years, 7 months ago by berry metal.
    Moderator bcworkz

    (@bcworkz)

    If what you want is consistently logical it’s likely possible to do. It’d mainly be a matter of how much extra work it would be to code it. The order of terms in the returned array from wp_get post_terms() is officially undefined, but appears to be the order terms appear in one of the tables. There are 3 related tables, I’m unsure which one, their ordering is usually very similar anyway. It’s not something to rely upon in any case.

    The get_adjacent_post() functions are limited in what sort of logic you can apply. Getting an adjacent post that has all matching terms isn’t within its capability AFAICT. However, you could do so with get_posts(). Limit its results to one “posts_per_page” which has a date greater (or less) than the current post’s, depending on if you want next or previous post. That much is essentially what get_adjacent_post() does without any category restrictions. Except it makes its own equivalent query, it doesn’t actually go through get_posts().

    You can then further restrict the get_posts() query by any other criteria you like. Limit posts by category criteria with “category__and” or “tax_query” args. “tax_query” allows you to apply very complex taxonomy term criteria if you so desired.

    It looks like you’d need to do more than modify the next-prev.php snippet you posted. All that does is merge different filtered settings into (most likely) the same category arg of get prev/next post functions. You likely would need to replace the get next/prev post functions on relevant templates with your own custom functions that do exactly as you wish.

    Thread Starter berry metal

    (@erikalleman)

    Indeed there is a template, this is the part of it that disp;lays the links:

    // Display previous  and next link
    	if ( 'true' == $previous_link ) {
    
    		$get_prev = get_previous_post( $in_same_term, '', $same_term_tax );
    
    		if ( $get_prev ) {
    
    			switch ( $link_format ) {
    				case 'icon':
    					$prev_format_escaped = ( 'true' == $reverse_order ) ? $icon_right : $icon_left;
    					break;
    				case 'title':
    					$title = get_the_title( $get_prev->ID );
    					$prev_format_escaped = ( 'true' == $reverse_order ) ? $title . $icon_right : $icon_left . $title;
    					break;
    				case 'custom':
    					$prev_format_escaped = ( 'true' == $reverse_order ) ? esc_html( $atts['previous_link_custom_text'] ) . $icon_right : $icon_left . esc_html( $atts['previous_link_custom_text'] ) ;
    					break;
    				default :
    					$prev_format_escaped = '';
    					break;
    			}
    
    			if ( $prev_format_escaped ) {
    
    				$prev = '<a href="' . esc_url( get_permalink( $get_prev->ID ) ) . '" class="' . esc_attr( $button_class ) . ' themeprefix-text-center themeprefix-max-w-100"' . $button_style_escaped . '>' . $prev_format_escaped . '</a>';
    
    			}
    
    		}
    
    	}
    
    	if ( 'true' == $next_link ) {
    
    		$get_next = get_next_post( $in_same_term, '', $same_term_tax );
    
    		if ( $get_next ) {
    
    			switch ( $link_format ) {
    
    				case 'icon':
    					$next_format_escaped = ( 'true' == $reverse_order ) ? $icon_left : $icon_right;
    					break;
    				case 'title':
    					$title = get_the_title( $get_next->ID );
    					$next_format_escaped = ( 'true' == $reverse_order ) ? $icon_left . $title : $title . $icon_right;
    					break;
    				case 'custom':
    					$next_format_escaped = ( 'true' == $reverse_order ) ? $icon_left . esc_html( $atts['next_link_custom_text'] ) : esc_html( $atts['next_link_custom_text'] ) . $icon_right;
    					break;
    				default:
    					$next_format_escaped = '';
    					break;
    
    			}
    
    			if ( $next_format_escaped ) {
    
    				$next = '<a href="' . esc_url( get_permalink( $get_next->ID ) ) . '" class="' . esc_attr( $button_class ) . ' themeprefix-text-center themeprefix-max-w-100"' . $button_style_escaped . '>' . $next_format_escaped . '</a>';
    
    			}
    
    		}
    
    	}

    Do you think anything else is missing for us to be able to make filter that would be placed in my child theme and it would alter the functioning of the next/prev buttons, if in_same_term is set to true?

    But the expression “in same term” is confusing for me.
    The terms doesn’t contain the posts, the terms are assigned to the posts.
    So “in same term” means, to me: has same term.

    So to achieve what I want the in_same_term conditional doesn’t matter anymore, right?

    Because what we want is a total match of terms, indifferent of their order and their count, so to check how many terms are there is also unnecessary, perhaps?

    And this is how get_adjacent_post works, I am trying to make something out of it:

    if ( $in_same_term ) {
                $join  .= " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
                $where .= $wpdb->prepare( 'AND tt.taxonomy = %s', $taxonomy );
    
                if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) ) {
                    return '';
                }
                $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
    
                // Remove any exclusions from the term array to include.
                $term_array = array_diff( $term_array, (array) $excluded_terms );
                $term_array = array_map( 'intval', $term_array );
    
                if ( ! $term_array || is_wp_error( $term_array ) ) {
                    return '';
                }
    
                $where .= ' AND tt.term_id IN (' . implode( ',', $term_array ) . ')';
            }
    • This reply was modified 3 years, 7 months ago by berry metal.
    Moderator bcworkz

    (@bcworkz)

    Don’t try to read too much into the meaning of $in_same_term. It’s really just a label. What’s meaningful is it causes essentially this to be added to the query:
    " AND tt.term_id IN ( $term_array )"
    $term_array being the term IDs of the current post. IN means tt.term_id of posts in the table can match anything in $term_array.

    If that doesn’t work for you, what’s significant is it’s not filterable, so you’d need to make your own query and thus your own function to go along with it. There are many ways to make your own query. Using get_posts() to return the one next|previous post is as good as any. In order to do that, you need your own function to replace get_{next|previous}_post() functions on the template. As long as your function returns one appropriate post object, it’ll be a drop-in replacement.

    You can use the get_adjacent_post() source code as guidance on how to collect relevant information, but I’d advise against trying to construct your own SQL query like the function does, unless you’re a lot better at SQL than I think you are ??

    BTW, please disregard what I said earlier about getting just the post links. It’s not a good fit now that I’ve seen the template code. You need to get the entire post object in each direction.

    Thread Starter berry metal

    (@erikalleman)

    We are getting closer, so far this is the code, but it only solves the problem half-way, the matching mechanism for all terms (and no extra terms allowed) is still missing (the “else” part).

    // Filter next/prev theme template.
    add_filter( 'wpex_next_prev_in_same_term', function( $check ) {
    
        if ( is_singular( 'post' ) ) {
    
            $categories = get_the_terms( get_the_ID(), 'category' );
    
            // If there is only 1 category then next/prev should be from the same category.
            // Otherwise they shouldn't be.
            if ( $categories && ! is_wp_error( $categories ) && 1 == count( $categories ) ) {
                $check = true;
            } else {
                $check = false;
            }
        }
    
        return $check;
    } );
    
    // Filter next/prev builder button attributes.
    add_filter( 'pluginprefix_shortcode_atts', function( $atts, $shortcode ) {
    
        if ( 'pluginprefix_post_next_prev' ===  $shortcode && is_singular( 'post' ) ) {
    
            $categories = get_the_terms( get_the_ID(), 'category' );
    
            // If there is only 1 category then next/prev should be from the same category.
            // Otherwise they shouldn't be.
            if ( $categories && ! is_wp_error( $categories ) && 1 == count( $categories ) ) {
                $atts['in_same_term'] = 'true';
            } else {
                $atts['in_same_term'] = 'false';
            }
        }
    
        return $atts;
    }, 10, 2 );

    Can we use something like this for the “else” part?

    $args= array(
        'post_type' => 'post',
        'posts_per_page' => '1',
        'orderby' => 'rand',
        'tax_query' => array(
            'relation' => 'AND',
            array(
                'relation' => 'OR',
                array(
                    'taxonomy' => 'category',
                    'field' => 'slug',
                    'terms' => 'category-1',
                ),
                array(
                    'taxonomy' => 'category',
                    'field' => 'slug',
                    'terms' => 'category-2',
                ),
                array(
                    'taxonomy' => 'category',
                    'field' => 'slug',
                    'terms' => 'category-3',
                ),
                array(
                    'taxonomy' => 'category',
                    'field' => 'slug',
                    'terms' => 'category-4',
                ),
            ),
            array(
                'taxonomy' => 'category',
                'field' => 'slug',
                'terms' => 'category-5',
            ),
        )
    );

    And modify the OR to AND?
    Would that be a complete solution?

    Thread Starter berry metal

    (@erikalleman)

    Oh and if it’s still not clear what is my objective, here is an example:

    With the native WP get_next_post mechanism with in_same_term set to true that my current buttons use, if current post has terms A, B and C, it would fetch next post that has A and C only, or A only, or A and B only, it would would even fetch a post that has A, B, C and D.
    In contrast, what I need is:

    If the current post has terms A, B, and C, the next/prev posts must also have all terms A, B and C, and no extras like D should be allowed, meaning: identic array of terms.

    So A and C only, or A only, or A and B only or A B C D shouldn’t be allowed.

    • This reply was modified 3 years, 7 months ago by berry metal.
    Thread Starter berry metal

    (@erikalleman)

    And with this mechanism there is no need to check how many terms are there. I noticed array_intersect() in PHP to match identic arrays, but I don’t know how to implement it.

    Thread Starter berry metal

    (@erikalleman)

    Hold on, I found the solution. I will be posting after testing.

    Thread Starter berry metal

    (@erikalleman)

    I still didn’t find the solution.

    But I got the format of the filter that we are supposed to use (instead of a standalone shortcode), and a partial fix, the exclusion of “extra” terms.

    So for example if the current post has terms A and B, this code won’t be able to match all terms A and B inclusively, but it will make sure that no extra terms like C will be considered. They will be excluded. The code:

    function my_exclude_next_prev_terms( $excluded_terms ) {
    
    	if ( is_singular( 'post' ) ) {
    
    		// Get current post categories.
    		$post_categories = get_the_terms( get_the_ID(), 'category' );
    		$post_categories = wp_list_pluck( $post_categories, 'term_id' ); // get ID's only
    
    		// If there are more then 1 category assined to the post, exclude all other terms
    		if ( $post_categories && ! is_wp_error( $post_categories ) && count( $post_categories ) > 1 ) {
    
    			// Define new excluded terms array.
    			$excluded_terms = array();
    
    			// Get all categories
    			$all_categories = get_terms( array(
    					'taxonomy'   => 'category',
    					'hide_empty' => false,
    				) );
    				$all_categories = wp_list_pluck( $all_categories, 'term_id' ); // get ID's only
    
    			// Loop through all categories and if they aren't part of the current post add them to the excluded list.
    			foreach ( $all_categories as $category ) {
    
    				// Category isn't a part of the current post so add it to the excluded terms.
    				if ( ! in_array( $category, $post_categories ) ) {
    					$excluded_terms[] = $category;
    				}
    
    			}
    
    		}
    
    	}
    
    	return $excluded_terms;
    }
    add_filter( 'get_previous_post_excluded_terms', 'my_exclude_next_prev_terms' );
    add_filter( 'get_next_post_excluded_terms', 'my_exclude_next_prev_terms' );

    Now only the query is left.

    In addition to the code above,
    I am supposed to filter the JOIN clause in the SQL for an adjacent post query.
    https://developer.www.ads-software.com/reference/hooks/get_adjacent_post_join/

    so that it changes from OR to AND.

    Or only to hook into it.

    But why is there no query in the template code?

    I don’t see any actual next/prev query in the theme code.
    That’s because it uses the default get_next_post query, right?
    This one: " AND tt.term_id IN ( $term_array )"
    But this is not a standalone query.
    Where is the rest of it?

    get_next_post is based on OR, because if one term only matches, it will fetch the post.
    But I don’t see any OR clause in this code:

    if ( $in_same_term ) {
                $join  .= " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
                $where .= $wpdb->prepare( 'AND tt.taxonomy = %s', $taxonomy );
    
                if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) ) {
                    return '';
                }
                $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
    
                // Remove any exclusions from the term array to include.
                $term_array = array_diff( $term_array, (array) $excluded_terms );
                $term_array = array_map( 'intval', $term_array );
    
                if ( ! $term_array || is_wp_error( $term_array ) ) {
                    return '';
                }
    
                $where .= ' AND tt.term_id IN (' . implode( ',', $term_array ) . ')';
            }

    So where is that OR defined?
    Ah, it’s here:
    " AND tt.term_id IN ( $term_array )"

    This structure of array is an AND statement:

    'tax_query' => array(
        array (
        'taxonomy' => 'category',
        'terms' => array('events'),
        'field' => 'slug'
        ),
       array ( 
      'taxonomy' => 'category',
      'terms' => array('featured'),
      'field' => 'slug'
       )
    )

    We have to use something like this, right?
    Is it necessary to integrate a get_post() with tax_query into the template code, by a filter, or is hooking into get_adjacent_post_join sufficient?

    But why not gather all arrays that need to be compared and then do array_diff or array_intersect or both to determin if it’s a match?

    Is it possible to use all the existing php language in WordPress, or is it limited by WordPress?

    I am reading this in PHP docs:

    The array_intersect() function compares the values of two (or more) arrays, and returns the matches.

    It’s exactly what we need, but I don’t know how to code this.

    I would need to modify this code example:

    add_filter( ‘get_next_post_join’, ‘navigate_in_same_taxonomy_join’, 20);
    add_filter( ‘get_previous_post_join’, ‘navigate_in_same_taxonomy_join’, 20 );
    function navigate_in_same_taxonomy_join() {
    global $wpdb;
    return ” INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id”;
    }
    
    add_filter( ‘get_next_post_where’ , ‘navigate_in_same_taxonomy_where’ );
    add_filter( ‘get_previous_post_where’ , ‘navigate_in_same_taxonomy_where’ );
    function navigate_in_same_taxonomy_where( $original ) {
    global $wpdb, $post;
    $where = ”;
    $taxonomy = ‘category’;
    $op = (‘get_previous_post_where’ == current_filter()) ? ‘<‘ : ‘>’;
    $where = $wpdb->prepare( “AND tt.taxonomy = %s”, $taxonomy );
    if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) )
    return $original ;
    
    $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( ‘fields’ => ‘ids’ ) );
    
    $term_array = array_map( ‘intval’, $term_array );
    
    if ( ! $term_array || is_wp_error( $term_array ) )
    return $original ;
    
    $where = ” AND tt.term_id IN (” . implode( ‘,’, $term_array ) . “)”;
    return $wpdb->prepare( “WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = ‘publish’ $where”, $post->post_date, $post->post_type );
    }

    to be inclusive for all terms.

    I can see that it’s possible to equal terms with an array:

    $todo_args = array(
       'cat' => $my_category_id,
       'posts_per_page' => 1,
       'tax_query' => array(
                array(
                   'taxonomy' => 'postkicker',
                    'field'    => 'slug',
                    'terms'    => array('monthly-to-do-list','community-events'),
                    ),
                ),
        'orderby' => 'date',
        'order' => 'DESC'
    );

    Or can we use has_term for the matching?
    https://developer.www.ads-software.com/reference/functions/has_term/

    That also only seems to have the OR operator, and not the AND. “Any of given terms.”

    And I found some other related stuff:

    function ss_get_post_ids($term, $taxonomy)
    {
        return get_posts(array(
            'post_type' => 'project', // if you are using a CPT, put it here. 
            'numberposts'   => -1,
            'tax_query'     => array(
                array(
                    'taxonomy'  => $taxonomy,
                    'field'     => 'id',
                    'terms'     => is_array($term) ? $term : array($term),
                ),
            ),
            'fields'        => 'ids',
        ));
    }
    $mytermid = '5'; // put your current term_id here
    $mytaxonomy = 'project-type'; // put your current taxonomy slug here
    $relatedposts = ss_get_post_ids($mytermid, $mytaxonomy); // call our function above to get all the ids for this pair
    
    global $post; 
    $currentpostID = $post->ID; // get current post ID   
    $currentKey = array_search($currentpostID, $relatedposts); //find current ID in our returned list of IDs to use it as base
    
    // below get the previous and next IDs, and loop back to beginning if at end
    $before = (isset($relatedposts[$currentKey - 1])) ? $relatedposts[$currentKey - 1] : $relatedposts[count($relatedposts) - 1];
    $after = (isset($relatedposts[$currentKey + 1])) ? $relatedposts[$currentKey + 1] : $relatedposts[0];
    
    // get the previous and next permalinks using the IDs above
    $term_previous_post_link = get_permalink($before);
    $term_next_post_link = get_permalink($after);

    Andf then use $term_previous_post_link and $term_next_post_link in the place of WordPress’ own next and prev post links.

    Why do you have to do

    ‘posts_per_page’ => 1

    if there are no pages in question and you don’t actually want to display any posts (only post links)?

    That is confusing me.

    And I found this code in a plugin that is trying to match the array instead of whichever term:

    // find first post in the adjacent interval
    		$next_posts = self::get_posts( array(
    			'_sn_post' => get_queried_object(),
    			'_sn_op' => $previous ? '<' : '>',
    			'order' => $previous ? 'DESC' : 'ASC',
    			'posts_per_page' => 2,
    			'paged' => 1
    		) );
    
    		if ( empty( $next_posts ) )
    			return 0;
    
    		$post = reset( $next_posts );
    
    		if ( count( $next_posts ) == 1 )
    			return $post->ID;
    
    		// there's more than one post in the adjacent interval, so need to get the first/last one
    		$final_posts = self::get_posts( array(
    			'_sn_post' => $post,
    			'_sn_op' => '=',
    			'order' => 'ASC',
    			'nopaging' => true,
    		) );
    
    		if ( $previous )
    			return reset( $final_posts )->ID;
    
    		return end( $final_posts )->ID;
    	}
    
    	private static function get_posts( $args = array() ) {
    		$args =	array_merge( self::$data['query'], $args, array(
    			'ignore_sticky_posts' => true
    		) );
    
    		$q = new WP_Query( $args );
    
    		return $q->posts;
    	}
    
    	static function posts_clauses( $bits, $wp_query ) {
    		global $wpdb;
    
    		$op = $wp_query->get( '_sn_op' );
    		$post = $wp_query->get( '_sn_post' );
    
    		if ( !$op )
    			return $bits;
    
    		$orderby = preg_split( '|\s+|', $bits['orderby'] );
    		$orderby = reset( $orderby );
    
    		$field = explode( '.', $orderby );
    		$field = end( $field );
    
    		if ( isset( $post->$field ) ) {
    			$bits['where'] .= $wpdb->prepare( " AND $orderby $op %s ", $post->$field );
    		} else {
    			$bits['where'] = ' AND 1 = 0';
    		}
    
    		return $bits;
    }

    Should we use get_the_terms or wp_get_object_terms?

    And this maybe could be useful?

    $terms = get_the_terms($this_post,'post_tag');
    if (!is_wp_error($terms)) {
      $terms = wp_list_pluck($terms,'term_id');
      $args['tax_query'] = array(
        array(
          'taxonomy' => 'post_tag',
          'field' => 'id',
          'terms' => array_values($terms)
        )
      );
      $query = new WP_Query($args);
    }

    Which of all these could be useful?

    Moderator bcworkz

    (@bcworkz)

    The “join” filter isn’t the one you want to accomplish what you want. That one allows us to bring in additional tables into the query. The term relationship table is already joined in, it’s all you should need.

    The filter you could use is "get_{$adjacent}_post_where". You’d actually hook two filters because $adjacent could equal “next” or “previous”.

    The SQL is assembled from bits and bobs created in different parts of the source code. It’s not that easy to see the entire query at once. Your best option to do so would be to use the Query Monitor plugin to see all SQL queries made in a request. Find the queries for caller get_adjacent_post() in the plugin’s queries tab.

    The problem with using the “where filter” is you cannot simply replace ORs with ANDs because the ones to change don’t exist. The OR logic is achieved through the IN () syntax. You’d need to convert something like x IN (1,2,3) into a sub-query that gets all post IDs that are common to term IDs 1, 2, and 3 respectively. Sort of an inverse IN () logic. Do this all through PHP string manipulation. String manipulation of SQL queries is inherently fragile as it is. I think this sort of change is asking for trouble. This is why I recommend making your own function and your own query instead of trying to filter the existing.

    Using the “tax_query” arg of get_posts() or WP_Query class allows you to construct very elaborate term criteria, but you would likely be able to simply use “category__and”.

    We use the 'posts_per_page' => 1, arg to limit the number of matching posts returned because we only want the nearest adjacent post, not all posts later or earlier. The arg simply translates into a SQL LIMIT 1 clause. Again, don’t try to read too much into “posts_per_page”, it’s just a label. What it actually accomplishes is all that matters. “numberposts” is a synonym for the same arg. However “numberposts” is slated to be deprecated in favor of “posts_per_page”.

    You’d declare a function for each direction, or include a parameter for direction like get_adjacent_post() does. The function would get the current post’s date and its assigned category terms in the form of an array of term IDs (assigned to $term_ids for example). Then use get_posts() to get 1 post whose date is later|earlier than current. Order the return by post date ascending or descending, depending on the direction we’re going, so we only get the very next or earlier post. Restrict possible posts returned with 'category__in => $term_ids,

    When you get the current post’s terms, use the 'fields' => 'ids', arg so only the IDs are returned. The array returned can be assigned directly to $term_ids.

    Moderator bcworkz

    (@bcworkz)

    I removed the moderation watch from your account. Be careful in the future to not use plugin reviews as a way to get support. Also be sure you don’t offer login credentials to anyone in these forums, even those you feel are totally trustworthy. Privileged access to other’s sites instills significant liability that most don’t realize they are incurring. Even if all is on the up and up, it sets a bad example.

    Thread Starter berry metal

    (@erikalleman)

    I found the queries with Query Monitor:

    SELECT p.ID
    FROM wptq_posts AS p
    LEFT JOIN wptq_postmeta AS m
    ON ( p.ID = m.post_id
    AND m.meta_key = 'themeprefix_post_link' )
    WHERE p.post_date < '2018-04-04 15:22:44'
    AND p.post_type = 'post'
    AND ( p.post_status = 'publish'
    OR p.post_status = 'private' )
    AND ( (m.meta_key = 'themeprefix_post_link'
    AND CAST(m.meta_value AS CHAR) = '' )
    OR m.meta_id IS NULL )
    ORDER BY p.post_date DESC
    LIMIT 1
    SELECT p.ID
    FROM wptq_posts AS p
    LEFT JOIN wptq_postmeta AS m
    ON ( p.ID = m.post_id
    AND m.meta_key = 'themeprefix_post_link' )
    WHERE p.post_date > '2018-04-04 15:22:44'
    AND p.post_type = 'post'
    AND ( p.post_status = 'publish'
    OR p.post_status = 'private' )
    AND ( (m.meta_key = 'themeprefix_post_link'
    AND CAST(m.meta_value AS CHAR) = '' )
    OR m.meta_id IS NULL )
    ORDER BY p.post_date ASC
    LIMIT 1

    If I use the AND operator in tax_query, I don’t need to use category__and, is that right?

    I did not test this because I know it’s wrong, but this is what I managed to write based on your instructions (and googleing) :

    function in_same_term_next_post_link ($term_ids, $post_categories, $limit = 1, $next_post, $adjacents) {
    
        global $wpdb, $post;
    
        $next_post = $wpdb->get_results( "
       (
           SELECT
               
               p1.post_date,
               
           FROM
               $wpdb->posts next_post1
                    INNER JOIN wp_term_relationships
                    AS tr
                    ON next_post1.ID = tr.object_id
                    INNER JOIN wp_term_taxonomy tt
                    ON tr.term_taxonomy_id = tt.term_taxonomy_id
           WHERE
               p1.post_date > '$date' AND
               
               p1.post_status = 'publish'
                    AND tt.taxonomy = '$taxonomy'
                    AND tt.term_id
                    IN ($term_id)
           ORDER by next_post1.post_date DESC
           LIMIT $limit
    	   )
            " );
    
        $adjacents = array();
        $adjacents['next'] = array();
    
        for( $i=0; $i<count($n); $i++ ) {
            $adjacents['next'][] = $n[$i];
        }    
     
        return $adjacents;
    }
    
        $post_categories = get_the_terms( get_the_ID(), 'category' );
    	$post_categories = wp_list_pluck( $post_categories, 'term_id' ); // get ID's only
    
        $current_post_date = $post->post_date;
    
        $term_ids = array();
    
            get_posts(array(
    
                'post_type' => 'post',
                'posts_per_page' => 1,
                'tax_query'     => array(
    
                	'relation' => 'AND',
                    array(
                    [post_date] => 
                    'taxonomy'  => $category,
                    'fields'        => 'ids',
                    category__in => $term_ids,
                    'terms'     => is_array($term) ? $term : array($term),
                    'order'             => 'ASC',
    
                ),
            ),
            
        ));
    
            return $term_ids;
    
    }
    
    echo '<li><a href="'.get_permalink( $term_ids ).'">'.get_the_title( $term_ids ).'</a></li>';

    Could you help correct it and with a correct example code?

    This is just the next link, I can write the previous link alone based on the correct next link.

    This function returns an array of IDs, $term_ids, containin a single ID, that of the curretn post, and $next_post returns a single post (I could grab its ID), whose date is the next adjacent date in the future, so should I have used $next_post for the permalink, instead?

    So the string format database query in the code is not necessary?

    Is this the same query just in 2 different formats?

    Thanks!

    • This reply was modified 3 years, 7 months ago by berry metal.
    • This reply was modified 3 years, 7 months ago by berry metal.
    • This reply was modified 3 years, 7 months ago by berry metal.
    • This reply was modified 3 years, 7 months ago by berry metal.
Viewing 15 replies - 16 through 30 (of 63 total)
  • The topic ‘get_next_post options’ is closed to new replies.