WordPress.org

Forums

[resolved] Can't exclude a category from the previous_post_link and next_post_link (26 posts)

  1. randycarl67
    Member
    Posted 5 years ago #

    I am unable to exclude a category from the previous_post_link and next_post_link in single.php.

    The category I want to exclude is id # 1 - named "View All".

    The View All category is the default category for all posts.

    Every post is in 2 categories; a specific category like "Baby & Children" as well as the View All category.

    Here is the Previous and Next link code in single.php.

    <?php previous_post_link('%link', 'Previous', TRUE, '1'); ?>
    <?php next_post_link('%link', 'Next', TRUE, '1'); ?>

    I need to not show the "View All" category just the items specific category.

  2. vtxyzzy
    Member
    Posted 5 years ago #

    I wonder if the fact that all posts are in the View All category is causing the problem because of the TRUE for in_same_cat.

    Try removing the View All from one post and see if the links work for that post.

  3. randycarl67
    Member
    Posted 5 years ago #

    Yup works just fine - If I remove the View All category from a specific category like Baby & Children.

    Now I'd really like to have a "View All" category...Is there anyway to have a "View All" category or a "Show All"? The website is very visual with every post being an image with a description and "View All" is a great way to show off.

  4. vtxyzzy
    Member
    Posted 5 years ago #

    I would say that may be a bug in WP. At line 886 in wp-includes/link-template.php there is this:

    $excluded_categories = array_diff($excluded_categories, $cat_array);

    where the categories that the post is in ($cat_array) are taken out of $excluded_categories. I think it should be the other way around. That is, excluded categories should be removed from the list that the post is in.

    If you want to hack the core code, try changing this (a few lines earlier) CAUTION UNTESTED:

    if ( $in_same_cat ) {
       $cat_array = wp_get_object_terms($post->ID, 'category', 'fields=ids');
       $join .= " AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $cat_array) . ")";
    }

    to this:

    if ( $in_same_cat ) {
       $cat_array = wp_get_object_terms($post->ID, 'category', 'fields=ids');
       if (!empty($excluded_categories)) {
          $cat_array = array_diff($cat_array,$excluded_categories);
       }
       if (!empty($cat_array) ) {
          $join .= " AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $cat_array) . ")";
       }
    }
  5. vtxyzzy
    Member
    Posted 5 years ago #

    I think I have a temporary solution. Paste the code below onto the end of your functions.php file. It adds a filter to take the excluded post id(s) out of the join statement.

    <?php
    // Remove excluded categories from previous/next_post_link join statement
    // Author: Mac McDonald
    // Contact: Use 'Contact Us' form under 'About' at bluegrassmiataclub.com
    function pnp_link_joinfilter ($join,$in_same_cat,$excluded_categories) {
       $new_join = $join;
       if ($in_same_cat && $excluded_categories) {
          preg_match('/\(((\d+,?)+)\)/',$join,$matches);
          if ($matches) $old_cats = $matches[1];
          $new_cats = $old_cats . ',';
          foreach ($excluded_categories as $ex) {
             $new_cats = preg_replace("/$ex,/",'',$new_cats);
          }
          $new_cats = preg_replace('/,$/','',$new_cats);
          if ($new_cats != '') {
             $new_join = preg_replace("/$old_cats/", $new_cats, $new_join);
          }
       }
       return $new_join;
    }
    add_filter('get_previous_post_join','pnp_link_joinfilter');
    add_filter('get_next_post_join','pnp_link_joinfilter');
    ?>

    Note that if you try to remove all the categories that the post is in, nothing is changed.

  6. randycarl67
    Member
    Posted 5 years ago #

    Thank you for the help.

    However when I add the temp solution to the functions.php file, I get a php error:

    Fatal error: Call to undefined function add_filter() in /home/info/my-website.com/www/wp-includes/functions.php on line 3661

    <?php
    // Remove excluded categories from previous/next_post_link join statement
    // Author: Mac McDonald
    // Contact: Use 'Contact Us' form under 'About' at bluegrassmiataclub.com
    function pnp_link_joinfilter ($join,$in_same_cat,$excluded_categories) {
       $new_join = $join;
       if ($in_same_cat && $excluded_categories) {
          preg_match('/\(((\d+,?)+)\)/',$join,$matches);
          if ($matches) $old_cats = $matches[1];
          $new_cats = $old_cats . ',';
          foreach ($excluded_categories as $ex) {
             $new_cats = preg_replace("/$ex,/",'',$new_cats);
          }
          $new_cats = preg_replace('/,$/','',$new_cats);
          if ($new_cats != '') {
             $new_join = preg_replace("/$old_cats/", $new_cats, $new_join);
          }
       }
       return $new_join;
    }
    add_filter('get_previous_post_join','pnp_link_joinfilter');
    add_filter('get_next_post_join','pnp_link_joinfilter');
    ?>
  7. vtxyzzy
    Member
    Posted 5 years ago #

    What version of WP are you using? It was tested for 2.8.6. Also, add it to the end of your theme's functions.

  8. randycarl67
    Member
    Posted 5 years ago #

    I'm on 2.9.1. And it was at the very end of the functions.php.

  9. vtxyzzy
    Member
    Posted 5 years ago #

    But the error message says it is at the end of wp-includes/functions.php, not wp-content/themes/mytheme/functions.php.

  10. randycarl67
    Member
    Posted 5 years ago #

    Well - Duh! I guess I was looking at this so long that I missed the simple instructions for mytheme/functions.php.

    I did add it to mythemes/functions.php and it completely broke the website. Nothing would load, just blank.

    Sorry for being such a bother. And thank you!

  11. vtxyzzy
    Member
    Posted 5 years ago #

    Well, I am sorry. I don't have a way to test on 2.9.1 at present.

    What theme are you using? I can at least test that in 2.8.6.

  12. randycarl67
    Member
    Posted 5 years ago #

    I'm using Fotofolio...http://demo.wordspop.com/fotofolio/

    http://wordspop.com/themes/fotofolio/

  13. vtxyzzy
    Member
    Posted 5 years ago #

    OK - after a few adjustments, it should work now. I apologize for the lack of earlier testing.

    One other change: to get the excluded ids passed through link-template.php, code them as negatives. So, to exclude category '1', code it as '-1' whenever you use in_same_cat as TRUE.

    Please try this version:

    <?php
    // Remove excluded categories from previous/next_post_link join statement
    // Code excluded categories as negative values eg '-15 and -4'.
    // Author: Mac McDonald
    // Contact: Use 'Contact Us' form under 'About' at bluegrassmiataclub.com
    function pnp_link_joinfilter ($join = null,$in_same_cat = false,$excluded_categories = '') {
       $new_join = $join;
       if ($join) {
          if ($in_same_cat && $excluded_categories) {
             preg_match('/\(((\d+,?)+)\)/',$join,$matches);
             if ($matches) $old_cats = $matches[1];
             $new_cats = $old_cats . ',';
             foreach ($excluded_categories as $ex) {
                $ex = abs($ex);
                $new_cats = preg_replace("/$ex,/",'',$new_cats);
             }
             $new_cats = preg_replace('/,$/','',$new_cats);
             if ($new_cats != '') {
                $new_join = preg_replace("/$old_cats/", $new_cats, $new_join);
             }
          }
       }
    
       return $new_join;
    }
    add_filter('get_previous_post_join','pnp_link_joinfilter',10,3);
    add_filter('get_next_post_join','pnp_link_joinfilter',10,3);
    ?>
  14. randycarl67
    Member
    Posted 5 years ago #

    Sorry but this doesn't work in WP 2.9.1. With that code the website is completely broken. Blank. Nothing. Busted.

  15. vtxyzzy
    Member
    Posted 5 years ago #

    I am confused. It works perfectly for me in WP 2.8.6 and in 2.9.1, which I just installed. I even loaded your theme to rule out theme problems.

    Can you post the end of your functions.php file including the last 10 or so lines above this code?

  16. randycarl67
    Member
    Posted 5 years ago #

    This is without your fix....

    function mooz_image_predata($post_id) {
    $post_id = (int) $post_id;
    if(!$post_id) return false;
    $max_width = wptp_getopt('img_width', 0);
    $max_height = wptp_getopt('img_height', 0);
    $switch = wptp_getopt('tim_url', 0);
    $image['id'] = wptp_get_image_attachment($post_id);
    if(empty($image['id'])) return false;
    if(empty($switch))
    $image['path'] = mooz_get_base_path($image['id']);
    else
    $image['path'] = mooz_get_base_url($image['id']);
    $image['size'] = mooz_get_ratio($image['id'], $max_width, $max_height);
    if(false == $image['size'])
    return false;
    return $image;
    }

    add_action('admin_menu', 'mooz_fotofolio_init');

    ?>

  17. vtxyzzy
    Member
    Posted 5 years ago #

    Strange. That does not match what I just downloaded. Are you using 'Fotofolio 1.0.8 by Pupung Budi Purnama'?

    Also, when you pasted in the fix, did you make sure there were no blank lines between the original end of the code and the start of the fix, and no blank lines after the fix?

    One reason I wanted to see the code including the fix was to see if anything got messed up in the copy/paste process.

    One other thing to check: do the calls to previous/next_post_link look like this?

    <?php previous_post_link('%link', wptp_getopt('nav_previous_value',0), wptp_getopt('nav_in_same_cat' , 0),'-1'); ?>

  18. randycarl67
    Member
    Posted 5 years ago #

    Nope. I'm using Fotofolio 1.0.6. And I had no spaces before or after the php code.

    I really appreciate all your time and effort on this but for some reason I guess I'm not gonna get this to work. I've the next/previous links on single.php.

    Maybe we'll be able to have this in a future upgrade of WP.

  19. vtxyzzy
    Member
    Posted 5 years ago #

    If you will zip up your theme folder and email it to me at m_a_mcdonald =at= bellsouth =dot= net, I will be happy to try to get it to work.

  20. vtxyzzy
    Member
    Posted 5 years ago #

    For anyone else looking for a fix, first try the filter code posted above. If this does not work, and you don't mind hacking the core files, here is what worked for randycarl67:

    In wp-includes/link-template.php, function get_adjacent_post, change this:

    if ( $in_same_cat ) {
       $cat_array = wp_get_object_terms($post->ID, 'category', 'fields=ids');
       $join .= " AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $cat_array) . ")";
    }

    to this:

    if ( $in_same_cat ) {
       $cat_array = wp_get_object_terms($post->ID, 'category', 'fields=ids');
       if ( !empty($excluded_categories) ) {
          $temp_excluded_categories = array_map('intval', explode(' and ', $excluded_categories));
          $new_cat_array = array_diff($cat_array, $temp_excluded_categories);
       }
       $join .= " AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $new_cat_array) . ")";
    }
  21. biochip
    Member
    Posted 5 years ago #

    For me is working another way without hacking the core: Duplicating, renaming and hacking the functions involved to functions.php from your template.

    Only need to insert "_2" to each function & the hack suggest by vtxyzzy in the "get_adjacent_post" function (our get_adjacent_post_2).

    function previous_post_link_2($format='&laquo; %link', $link='%title', $in_same_cat = false, $excluded_categories = '') {
    	adjacent_post_link_2($format, $link, $in_same_cat, $excluded_categories, true);
    }
    function next_post_link_2($format='%link &raquo;', $link='%title', $in_same_cat = false, $excluded_categories = '') {
    	adjacent_post_link_2($format, $link, $in_same_cat, $excluded_categories, false);
    }
    function adjacent_post_link_2($format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true) {
    	if ( $previous && is_attachment() )
    		$post = & get_post($GLOBALS['post']->post_parent);
    	else
    		$post = get_adjacent_post_2($in_same_cat, $excluded_categories, $previous);
    
    	if ( !$post )
    		return;
    
    	$title = $post->post_title;
    
    	if ( empty($post->post_title) )
    		$title = $previous ? __('Previous Post') : __('Next Post');
    
    	$title = apply_filters('the_title', $title, $post);
    	$date = mysql2date(get_option('date_format'), $post->post_date);
    	$rel = $previous ? 'prev' : 'next';
    
    	$string = '<a href="'.get_permalink($post).'" rel="'.$rel.'">';
    	$link = str_replace('%title', $title, $link);
    	$link = str_replace('%date', $date, $link);
    	$link = $string . $link . '</a>';
    
    	$format = str_replace('%link', $link, $format);
    
    	$adjacent = $previous ? 'previous' : 'next';
    	echo apply_filters( "{$adjacent}_post_link", $format, $link );
    }
    function get_adjacent_post_2($in_same_cat = false, $excluded_categories = '', $previous = true) {
    	global $post, $wpdb;
    
    	if ( empty($post) || !is_single() || is_attachment() )
    		return null;
    
    	$current_post_date = $post->post_date;
    
    	$join = '';
    	$posts_in_ex_cats_sql = '';
    	if ( $in_same_cat || !empty($excluded_categories) ) {
    		$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";
    
    //the hack
    if ( $in_same_cat ) {
       $cat_array = wp_get_object_terms($post->ID, 'category', 'fields=ids');
       if ( !empty($excluded_categories) ) {
          $temp_excluded_categories = array_map('intval', explode(' and ', $excluded_categories));
          $new_cat_array = array_diff($cat_array, $temp_excluded_categories);
       }
       $join .= " AND tt.taxonomy = 'category' AND tt.term_id IN (" . implode(',', $new_cat_array) . ")";
    }
    
    		$posts_in_ex_cats_sql = "AND tt.taxonomy = 'category'";
    		if ( !empty($excluded_categories) ) {
    			$excluded_categories = array_map('intval', explode(' and ', $excluded_categories));
    			if ( !empty($cat_array) ) {
    				$excluded_categories = array_diff($excluded_categories, $cat_array);
    				$posts_in_ex_cats_sql = '';
    			}
    
    			if ( !empty($excluded_categories) ) {
    				$posts_in_ex_cats_sql = " AND tt.taxonomy = 'category' AND tt.term_id NOT IN (" . implode($excluded_categories, ',') . ')';
    			}
    		}
    	}
    
    	$adjacent = $previous ? 'previous' : 'next';
    	$op = $previous ? '<' : '>';
    	$order = $previous ? 'DESC' : 'ASC';
    
    	$join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_cat, $excluded_categories );
    	$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare("WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_cats_sql", $current_post_date, $post->post_type), $in_same_cat, $excluded_categories );
    	$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );
    
    	$query = "SELECT p.* FROM $wpdb->posts AS p $join $where $sort";
    	$query_key = 'adjacent_post_' . md5($query);
    	$result = wp_cache_get($query_key, 'counts');
    	if ( false !== $result )
    		return $result;
    
    	$result = $wpdb->get_row("SELECT p.* FROM $wpdb->posts AS p $join $where $sort");
    	if ( null === $result )
    		$result = '';
    
    	wp_cache_set($query_key, $result, 'counts');
    	return $result;
    }

    And the call in the template

    <div class="alignleft"><?php previous_post_link_2('%link', '<', TRUE,'3,10') ?></div>
    <div class="alignright"><?php next_post_link_2('%link', '>', TRUE,'3,10'); ?></div>
  22. Tzaddi
    Member
    Posted 5 years ago #

    Biochip, THANK YOU for that code. It worked beautifully to fix a bug I had in a site.

  23. Electric Studio
    Member
    Posted 5 years ago #

    Hello, I'm using 2.9.2 and the biochip function does indeed remove the categories from the previous and next leinks, but it fails to show the titles of the same, any suggestions?

  24. Electric Studio
    Member
    Posted 5 years ago #

    I have come up with a solution thats works for me. In order to exclude categories on the previous and next postlinks on a single post page, use:

    <?php previous_post_link('« %link', '%title', FALSE, '13 and 16') ?>

    <?php next_post_link('%link »', '%title', FALSE, '13 and 16') ?>

    This will exclude all posts from 13 and 16. If you wish to exclude more, simple continue that string 13 and 16 and 21 and 34 and so on.

    Hope this helps.

  25. mrjoshuathomas
    Member
    Posted 5 years ago #

    Electric Studio thank you so much! I've been searching for hours to find this.

  26. jfuste
    Member
    Posted 4 years ago #

    Thanks Electric Studio, this little change makes my day! Also, big thanks to biochip for the code!

Topic Closed

This topic has been closed to new replies.

About this Topic