How to give paged links custom title?

I have split my post content into mutiple pages using the <! - nextpage -> code. I want to give my paginated links their own title instead of the regular 1,2,3. How can I do this? cause on this doc https://codex.wordpress.org/Styling_Page-Links it only mentions method to adding suffix or prefix. I just want to give each paged number their own custom title

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Here’s a way to support pagination titles of the form:

<!--nextpage(.*?)?-->

in a simlar way as the core supports <!--more(.*?)?-->.

Here’s an example:

<!--nextpage Planets -->
Let's talk about the Planets
<!--nextpage Mercury -->
Exotic Mercury
<!--nextpage Venus-->
Beautiful Venus
<!--nextpage Earth -->
Our Blue Earth
<!--nextpage Mars -->
The Red Planet

with the output similar to:

Pagination titles

This was tested on the Twenty Sixteen theme, where I had to adjust the padding and width a little bit:

.page-links a, .page-links > span {
    width:   auto;
    padding: 0 5px;
}

Demo plugin

Here’s a demo plugin that uses the content_pagination, wp_link_pages_link, pre_handle_404 and wp_link_pages_args filters to support this extenstion of the nextpage marker (PHP 5.4+):

<?php
/**
 * Plugin Name: Content Pagination Titles
 * Description: Support for &lt;!--nextpage(.*?)?--&gt; in the post content
 * Version:     1.0.1
 * Plugin URI:  http://wordpress.stackexchange.com/a/227022/26350
 */

namespace WPSEQuestion202709;

add_action( 'init', function()
{
    $main = new Main;
    $main->init();
} );

class Main
{
    private $pagination_titles;

    public function init()
    {
        add_filter( 'pre_handle_404',       [ $this, 'pre_handle_404' ],        10, 2       );
        add_filter( 'content_pagination',   [ $this, 'content_pagination' ],    -1, 2       );
        add_filter( 'wp_link_pages_link',   [ $this, 'wp_link_pages_link' ],    10, 2       );
        add_filter( 'wp_link_pages_args',   [ $this, 'wp_link_pages_args' ],    PHP_INT_MAX );
    }

    public function content_pagination( $pages, $post )
    {
        // Empty content pagination titles for each run
        $this->pagination_titles = [];

        // Nothing to do if the post content doesn't contain pagination titles
        if( false === stripos( $post->post_content, '<!--nextpage' ) )
            return $pages;

        // Collect pagination titles
        preg_match_all( '/<!--nextpage(.*?)?-->/i', $post->post_content, $matches );
        if( isset( $matches[1] ) )
            $this->pagination_titles = $matches[1];     

        // Override $pages according to our new extended nextpage support
        $pages = preg_split( '/<!--nextpage(.*?)?-->/i', $post->post_content );

        // nextpage marker at the top
        if( isset( $pages[0] ) && '' == trim( $pages[0] ) )
        {
            // remove the empty page
            array_shift( $pages );
        }       
        // nextpage marker not at the top
        else
        {
            // add the first numeric pagination title 
            array_unshift( $this->pagination_titles, '1' );
        }           
        return $pages;
    }

    public function wp_link_pages_link( $link, $i )
    {
        if( ! empty( $this->pagination_titles ) )
        {
            $from  = '{{TITLE}}';
            $to    = ! empty( $this->pagination_titles[$i-1] ) ? $this->pagination_titles[$i-1] : $i;
            $link  = str_replace( $from, $to, $link );
        }

        return $link;
    }

    public function wp_link_pages_args( $params )
    {       
        if( ! empty( $this->pagination_titles ) )
        {
            $params['next_or_number'] = 'number';
            $params['pagelink'] = str_replace( '%', '{{TITLE}}', $params['pagelink'] );
        }
        return $params;
    }

    /**
     * Based on the nextpage check in WP::handle_404()
     */
    public function pre_handle_404( $bool, WP_Query $q )
    {
        global $wp;

        if( $q->posts && is_singular() )
        {
            if ( $q->post instanceof WP_Post ) 
                $p = clone $q->post;

            // check for paged content that exceeds the max number of pages
            $next = '<!--nextpage';
            if (   $p 
                 && false !== stripos( $p->post_content, $next ) 
                 && ! empty( $wp->query_vars['page'] ) 
            ) {
                $page = trim( $wp->query_vars['page'], '/' );
                $success = (int) $page <= ( substr_count( $p->post_content, $next ) + 1 );

                if ( $success )
                {
                    status_header( 200 );
                    $bool = true;
                }
            }
        }
        return $bool;
    }

} // end class

Installation: Create the /wp-content/plugins/content-pagination-titles/content-pagination-titles.php file and activate the plugin. Always a good idea to backup before testing any plugin.

If the top nextpage marker is missing, then the first pagination title is numeric.

Also if a content pagination title is missing, i.e. <!--nextpage-->, then it will be numeric, just as expected.

I first forgot about the nextpage bug in the WP class, that shows up if we modify the number of pages via the content_pagination filter. This was recently reported by @PieterGoosen here in #35562.

We try to overcome that in our demo plugin with a pre_handle_404 filter callback, based on the WP class check here, where we check for <!--nextpage instead of <!--nextpage-->.

Tests

Here are some further tests:

Test #1

<!--nextpage-->
Let's talk about the Planets
<!--nextpage-->
Exotic Mercury
<!--nextpage-->
Beautiful Venus
<!--nextpage-->
Our Blue Earth
<!--nextpage-->
The Red Planet

Output for 1 selected:

test1

as expected.

Test #2

Let's talk about the Planets
<!--nextpage-->
Exotic Mercury
<!--nextpage-->
Beautiful Venus
<!--nextpage-->
Our Blue Earth
<!--nextpage-->
The Red Planet

Output for 5 selected:

test2

as expected.

Test #3

<!--nextpage-->
Let's talk about the Planets
<!--nextpage Mercury-->
Exotic Mercury
<!--nextpage-->
Beautiful Venus
<!--nextpage Earth -->
Our Blue Earth
<!--nextpage Mars -->
The Red Planet

Output for 3 selected:

test3

as expected.

Test #4

Let's talk about the Planets
<!--nextpage Mercury-->
Exotic Mercury
<!--nextpage Venus-->
Beautiful Venus
<!--nextpage Earth -->
Our Blue Earth
<!--nextpage Mars -->
The Red Planet

Output with Earth selected:

test4

as expected.

Alternatives

Another way would be to modify it to support pagination titles to be added with:

<!--pt Earth-->

It might also be handy to support a single comment for all pagination titles (pts):
<!--pts Planets|Mercury|Venus|Earth|Mars -->

or perhaps via custom fields?

Method 2

You can use filter wp_link_pages_link

First pass our custom string placeholder (This can be anything you like except string containing %, just for now I am using #custom_title#).

wp_link_pages( array( 'pagelink' => '#custom_title#' ) );

Then add our filter in functions.php. In callback function make an array of titles then check for the current page number and replace #custom_title# with value corresponding to current page number.

Example:-

add_filter('wp_link_pages_link', 'wp_link_pages_link_custom_title', 10, 2);
/**
 * Replace placeholder with custom titles
 * @param string $link Page link HTML
 * @param int $i Current page number
 * @return string $link Page link HTML
 */
function wp_link_pages_link_custom_title($link, $i) {

    //Define array of custom titles
    $custom_titles = array(
        __('Custom title A', 'text-domain'),
        __('Custom title B', 'text-domain'),
        __('Custom title C', 'text-domain'),
    );

    //Default title when title is not set in array
    $default_title = __('Page', 'text-domain') . ' ' . $i; 

    $i--; //Decrease the value by 1 because our array start with 0

    if (isset($custom_titles[$i])) { //Check if title exist in array if yes then replace it
        $link = str_replace('#custom_title#', $custom_titles[$i], $link);
    } else { //Replace with default title
        $link = str_replace('#custom_title#', $default_title, $link);
    }

    return $link;
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments