1

I'm using wp_list_pages() to show pages and subpages in a tree view and I need to add a "read more" as a sub-item right after the current page.

Example:

We are at the "Page tree"

  • Page one
  • Page two
  • Page tree
    READ MORE
  • Page four
  • Page five

I'm not sure if this is achieved with hooks or walker, any suggestion would be appreciate!

Code I'm using:

function dkc_list_subpgm() { 

global $post; 

if (is_singular('pgm') && $post->post_parent )  
      $childpages = 
      wp_list_pages(  array(
      'post_type' => 'pgm',
      'sort_column' => 'menu_order',
      'title_li' => '',
      'child_of' => $post->post_parent ,
      'echo' =>'0'            
        ));
else
      $childpages = 
      wp_list_pages(  array(
      'post_type' => 'pgm',
      'sort_column' => 'menu_order',
      'title_li' => '',
      'child_of' => $post->ID,
      'echo' =>'0' 
        ));

if ( $childpages ) {

$string = '<ul class="wpb_page_list">' . $childpages . '</ul>';
}

return $string;

}

add_shortcode('dkc_childpages', 'dkc_list_subpgm');

1 Answer 1

2

I would use a custom walker and then extend the Walker_Page::start_el() method, like so:

// Based on Walker_Page for WordPress v6.0
// @link https://github.com/WordPress/wordpress-develop/blob/6.0/src/wp-includes/class-walker-page.php#L105-L219

class My_Walker_Page extends Walker_Page {
    public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) {
        /* This checks if the current page in the list is the current page you're on.
         * - $current_object_id is the ID of the current page you're on
         * - $data_object->ID is the ID of the current page in the list
         */
        $is_current_page = ( (int) $current_object_id === (int) $data_object->ID );

        // This one adds the "read more" inside the link, i.e. before the </a> tag.
        if ( $is_current_page ) {
            $args['link_after'] .= ' READ MORE 1 (inside "a")';
        }

        // Call the parent method to build the (complete) <li ...><a ...>...</a> part.
        parent::start_el( $output, $data_object, $depth, $args, $current_object_id );

        // This one adds the "read more" outside the link, i.e. after the </a> tag,
        // but still inside the same or current LI element.
        if ( $is_current_page ) {
            $output .= ' READ MORE 2 (outside "a")';
        }
    }
}

Things to note:

  • You could instead use a conditional tag such as is_page( $data_object->ID ) or is_single( $data_object->ID ), but using the above (int) $current_object_id === (int) $data_object->ID is easier because it works regardless the post type.

  • Just choose one of the if ( $is_current_page ) { ... } blocks above, or use both if you want to.. :)

And then pass an instance of the above class to wp_list_pages() (via the walker argument), e.g.

// NOTE: It's up to you on how to load the PHP FILE which defines the My_Walker_Page
// class, but for example, require_once __DIR__ . '/includes/class-my-walker-page.php';

wp_list_pages( array(
    'walker' => new My_Walker_Page(),
) );

Additional Notes

  • Your dkc_list_subpgm() code could be simplified like so where I used just one wp_list_pages() instead of two:

    function dkc_list_subpgm() {
    
        global $post;
    
        $child_of = $post->ID;
        if ( is_singular( 'pgm' ) && $post->post_parent ) {
            $child_of = $post->post_parent;
        }
    
        $childpages = wp_list_pages( array(
            'post_type'   => 'pgm',
            'sort_column' => 'menu_order',
            'title_li'    => '',
            'child_of'    => $child_of,
            'echo'        => 0, // just use 0 (without quotes) and not '0'
            'walker'      => new My_Walker_Page(),
        ) );
    
        if ( $childpages ) {
            return '<ul class="wpb_page_list">' . $childpages . '</ul>';
        }
    
        return '';
    
    }
    
2
  • Hi there, almost worked, I'm using a post type (pgm) and tried to use is_singular but with no luck, also the page list now is showing a title "Pages" that it doesn't go away with title_li='' any ideas? I tried if ( is_singular('pgm') && $current_object_id = 0 )
    – Diana
    Commented Jun 13, 2022 at 17:10
  • Thanks for adding your full code to the question ( although you should've notified me.. =) ), but I edited it and removed the 'walker' => new My_Walker_Page(), part (so that my answer would be "valid"..). So please try the revised My_Walker_Page code in my answer, and let me know if it works now for you? (and you can also try the simplified dkc_list_subpgm function code..)
    – Sally CJ
    Commented Jun 14, 2022 at 0:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.