Skip Navigation

[Resolved] Continuous post pagination – show first/last link last/first posts

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 -
- 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 -

Supporter timezone: Asia/Karachi (GMT+05:00)

This topic contains 5 replies, has 2 voices.

Last updated by jorgel-4 1 year, 3 months ago.

Assisted by: Waqar.

Author
Posts
#2526553

Hi! Currently I have a CPT "portfolio" that has a navigation to prev and next post based on menu order. I followed this ticket https://toolset.com/forums/topic/previous-and-next-post-navigation-when-sorted-by-menu-order/

My code is:

// Porfolio paginations
// 
add_shortcode( 'next_post', 'next_shortcode' );
function next_shortcode($atts) {
            global $post;
            ob_start();
            next_post_link( '<span class="nav-next">%link</span> ', '%title' );
            $result = ob_get_contents();
            ob_end_clean();
            return $result;
}
   
add_shortcode( 'prev_post', 'prev_shortcode' );
            function prev_shortcode($atts) {
                        global $post;
                        ob_start();
                        previous_post_link( ' <span class="nav-previous">%link</span>', '%title' );
                        $result = ob_get_contents();
                        ob_end_clean();
            return $result;
}

// Customize Post Link Order
function my_custom_adjacent_post_where($sql) {
    if ( !is_main_query() || !is_singular() || 'portfolio' != get_post_type() )
        return $sql;
      
    $the_post = get_post( get_the_ID() );
    $patterns = array();
    $patterns[] = '/post_date/';
    $patterns[] = '/\'[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\'/';
    $replacements = array();
    $replacements[] = 'menu_order';
    $replacements[] = $the_post->menu_order;
    return preg_replace( $patterns, $replacements, $sql );
}
add_filter( 'get_next_post_where', 'my_custom_adjacent_post_where' );
add_filter( 'get_previous_post_where', 'my_custom_adjacent_post_where' );
function my_custom_adjacent_post_sort($sql) {
    if ( !is_main_query() || !is_singular() || 'portfolio' != get_post_type() )
        return $sql;
      
    $pattern = '/post_date/';
    $replacement = 'menu_order';
    return preg_replace( $pattern, $replacement, $sql );
}
add_filter( 'get_next_post_sort', 'my_custom_adjacent_post_sort' );
add_filter( 'get_previous_post_sort', 'my_custom_adjacent_post_sort' );

What I need is that when you are on the first post (hidden link) it shows as previous post the last post . And viceversa, in last post (hidden link) need to show first post as next post . Actually it didn't show anything in those 2 cases.
So the idea is to have like a continuos or loop navigation.

Is it possible?

Thanks in advance

#2526889

Waqar
Supporter

Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)

Hi,

Thank you for contacting us and I'd be happy to assist.

To achieve this, you'll need a new custom shortcode that can show the first or the last post's navigation link, as needed:


add_shortcode( 'first_last_post', 'first_last_shortcode' );
function first_last_shortcode($atts) {

	$a = shortcode_atts( array(
		'post_type' => '',
		'type' => '',
	), $atts );

	if( $a['type'] == 'first' ) {
		$order = 'ASC';
	} elseif ( $a['type'] == 'last' ) {
		$order = 'DESC';
	}

	if( (!empty($a['post_type'])) && (!empty($a['type'])) ) {
		$args = array(
			'posts_per_page'	=> 1,
			'post_type'			=> $a['post_type'],
			'post_status'		=> 'publish',
			'orderby'			=> 'menu_order',
			'order'				=> $order,
		);
		$posts_array = get_posts( $args );

		if(!empty($posts_array)) {

		}
		ob_start();
		echo '<span class="nav-'.$a['type'].'"><a href="'.get_the_permalink($posts_array[0]->ID).'" rel="'.$a['type'].'">'.get_the_title($posts_array[0]->ID).'</a> : '.ucfirst($a['type']).'</span>';
		$result = ob_get_contents();
		ob_end_clean();
		return $result;
	}

}

The above code snippet can be included through either Toolset's custom code feature ( ref: https://toolset.com/documentation/adding-custom-code/using-toolset-to-add-custom-code/ ) or through the active theme's "functions.php" file.

Next, please add "first_last_post" in the "Third-party shortcode arguments" section, at WP Admin -> Toolset -> Settings -> Front-end Content.

This shortcode can be used to show the first or the last post links, like this:


// First post link where post type is 'portfolio'
[first_last_post type="first" post_type="portfolio"]

// Last post link where post type is 'portfolio'
[first_last_post type="last" post_type="portfolio"]<br>

And in your content template, you can show these shortcodes within the conditional statements, so that when the next and previous post links are empty, the output from this new first/last post link is used:


[wpv-conditional if="( '[prev_post]' eq '' )"]
[first_last_post type="last" post_type="portfolio"]
[/wpv-conditional]
[wpv-conditional if="( '[prev_post]' ne '' )"]
[prev_post]
[/wpv-conditional]

[wpv-conditional if="( '[next_post]' eq '' )"]
[first_last_post type="first" post_type="portfolio"]
[/wpv-conditional]
[wpv-conditional if="( '[next_post]' ne '' )"]
[next_post]
[/wpv-conditional]

I hope this helps and please let me know if you need further assistance.

regards,
Waqar

#2526989

Thanks a lot for your help Waqar!

It's working great like that, but the problem is that I'm not using the pagination inside a regular posts view. How can I apply that condition and add it to an Elementor template? I'm trying this but is not working:
1- I followed this instructions hidden link Created a view with a filter by ID in shortcode attribute 'ids', show one result and apply the conditional shortcodes you sent me before.
2- Then I added the view's shortcode to Elementor template for Portfolios CPT like this:

[wpv-view name="first-portfolio-prev-link" cached="off" ids="[wpv-post-id]"] 

BUT there is a problem with shortcode because of this --- > ]"] <----. I already tried using shortcode widget and editor text but doesn't work.
3- As it is described here https://toolset.com/forums/topic/types-shortcode-in-views-shortcode-parameter-not-working-in-elementor/ I used the view inside a Toolset Content Template

[wpv-post-body view_template="first-portfolio-prev-link-temp"]

and the condition is not showing anything.

#2527871

Waqar
Supporter

Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)

Thank you for sharing this update.

Can you please share temporary admin login details, along with the link to the page where you're trying to use this? I'll be in a better position to suggest the next steps, accordingly.

Note: Your next reply will be private and making a complete backup copy is recommended before sharing the access details.

#2531051

Waqar
Supporter

Languages: English (English )

Timezone: Asia/Karachi (GMT+05:00)

Thank you for waiting as we had some unusually busy forum queue after the holidays.

I reviewed and tested the setup that you've shared and noticed that the view "First Portfolio Prev Link" was not needed.

These shortcodes work as expected from the content template "First Portfolio Prev Link", directly:


[first_last_post type="last" post_type="portfolio"]

[first_last_post type="first" post_type="portfolio"]

[prev_post] [next_post]

There is a limitation though in using the conditional statement in this content template because it is being called inside an Elementor template. When the conditional statement is used in this template, any double quotes used in the output are converted to their HTML entities and the final output on the front end is broken as a result.

If you'd like to show the first and last post's links, only when the previous or next post links are not available, you can customize the code for the shortcodes "next_post" and "prev_post", so that they output the 'last post link' or the 'first post link' through the newly registered shortcode ( "first_last_post" ), when their own link output is empty.

I hope this helps and for more personalized assistance around custom code, you can also consider hiring a professional from our list of recommended contractors:
https://toolset.com/contractors/

#2531173

Hi Waqar, thanks for your response.

I founded a solution following this next forum topics:
https://toolset.com/forums/topic/show-content-based-on-whether-there-is-a-post-before-or-after-the-current-post/
https://toolset.com/forums/topic/display-wpv-post-next-link-and-wpv-post-previous-link-as-raw-html-link/#post-619757

The conditional works in Elementor templates, the problem was using the shortcodes
[prev_post] or [next_post] inside it.

So for someone else, next to your code I added this code to functions.php

//Check adjacent posts
//
function ts_get_adjacent_post_url_func($atts) {
  global $post;
  $previous = ($atts['previous'] == "1");
  $adjacent = get_adjacent_post( false, '', $previous);
  return get_the_permalink($adjacent);
}
add_shortcode("ts_get_adjacent_post_url", "ts_get_adjacent_post_url_func");

Then I added the shortcode "ts_get_adjacent_post_url" in the "Third-party shortcode arguments" section, at WP Admin -> Toolset -> Settings -> Front-end Content.

And finally I used this shortcodes inside a text widget in Elementor template to display the links:

1- Link to last post in first portfolio previuos link:

[wpv-conditional if="( '[ts_get_adjacent_post_url previous='1']' eq '[wpv-post-url id='$current_page']' )"][first_last_post type="last" post_type="portfolio"][/wpv-conditional]

2- Link to first post in last portfolio next link:

[wpv-conditional if="( '[ts_get_adjacent_post_url previous='0']' eq '[wpv-post-url id='$current_page']' )"][first_last_post type="first" post_type="portfolio"][/wpv-conditional]
This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.