1

Lets say I have this menu:

Top
    |___    Sub 1
            |___    Sub Sub 1
            |___    Sub Sub 2
            |___    Sub Sub 3
            |___    Sub Sub 4
    |___    Sub 2
            |___    Sub Sub 1
            |___    Sub Sub 2
            |___    Sub Sub 3
            |___    Sub Sub 4
    |___    Sub 3
            |___    Sub Sub 1
            |___    Sub Sub 2
            |___    Sub Sub 3
            |___    Sub Sub 4
    |___    Sub 4
            |___    Sub Sub 1
            |___    Sub Sub 2
            |___    Sub Sub 3
            |___    Sub Sub 4

I can list that menu using this:

    if( 0 == $post->post_parent && 0 == count( $children ) )
        return;

    if( 0 == $post->post_parent )
    {
        $child_of = $post->ID;
    }
    else {
        $parents = get_post_ancestors( $post->ID );
        $child_of = end( $parents );
    }

    $args = array
    (
        'child_of' => $child_of,
        'echo' => 0,
        'title_li' => ''
    );

    $pages = wp_list_pages( $args );

This is fine but I don't want to show all page items. What I want is that only imediate children of the page you are on is shown.

So if I'm on page Top the menu should appear like so:

Top
    |___    Sub 1
    |___    Sub 2
    |___    Sub 3
    |___    Sub 4

If I'm on page Top/Sub 3 the menu should appear like so:

Top
    |___    Sub 1
    |___    Sub 2
    |___    Sub 3
            |___    Sub Sub 1
            |___    Sub Sub 2
            |___    Sub Sub 3
            |___    Sub Sub 4
    |___    Sub 4

And so on, so that it can work to any depth.

Rarst put up a nice answer but this was for when using WordPress menus. I'm looking for the same for wp_list_pages(). Looking for an answer that uses a Walker or filters/hooks. I know how to solve this problem with CSS but this doesn't fix the problem of unnecessary HTML being sent to the browser.

3 Answers 3

1

I have come up with my own solution but I'm not convinced it's the best.

    $parents = array( $post->ID );
    if( 0 != $post->post_parent )
    {
        $parents = array_merge( $parents, get_post_ancestors( $post->ID ) );
    }
    $child_of = end( $parents );

    $args = array
    (
        'child_of' => $child_of,
        'echo' => 0,
        'title_li' => '',
        'walker' => new chg_Sub_Page_Navigation_Walker( $parents )
    );

    $pages = wp_list_pages( $args );

Walker:

class chg_Sub_Page_Navigation_Walker extends Walker_Page
{
    var $parents = array();

    function __construct( $parents )
    {
        $this->parents = $parents;
    }

    function start_el( &$output, $page, $depth, $args, $current_page )
    {
        if( in_array( $page->post_parent, $this->parents ) )
            parent::start_el( &$output, $page, $depth, $args, $current_page );
    }

    function end_el( &$output, $page, $depth )
    {
        if( in_array( $page->post_parent, $this->parents ) )
            parent::end_el( &$output, $page, $depth );
    }
}
0

You can consider using a mixture of get_children() for the children of the page and page siblings and get_post_ancestors() for the ancestors:

global $post;

$pages =& get_children(array(
  'post_type' => 'page',
  'post_parent' => $post->ID,
));

$siblings = get_children(array(
  'post_type' => 'page',
  'post_parent' => $post->post_parent,
));

$ancestors = get_post_ancestors($post->ID);

Edit - a quick demonstration of the idea which can use some clean up:

<ul>
<?php
    global $post;

    $children =& get_children(array(
        'post_type' => 'page',
        'post_parent' => $post->ID,
    ));

    $siblings = get_children(array(
        'post_type' => 'page',
        'post_parent' => $post->post_parent,
    ));

    $ancestors = get_post_ancestors($post->ID);

    if(!empty($ancestors)):
        $ancestors = array_reverse($ancestors);
        foreach($ancestors as $aid):
            $p = get_post($aid);
            ?>
            <li>
                <?php echo $p->post_title ?>
                <ul>
        <?php endforeach?>

        <?php if(!empty($siblings)): ?>
            <?php foreach($siblings as $sibling): ?>
                <li>
                    <?php echo $sibling->post_title?>
                    <?php if($sibling->ID == $post->ID && !empty($children)): ?>
                        <ul>
                            <?php foreach($children as $child): ?>
                                <li><?php echo $child->ID ?></li>
                            <?php endforeach?>
                        </ul>
                    <?php endif ?>
                </li>
            <?php endforeach ?>
        <?php endif ?>

        <?php foreach ($ancestors as $aid):?>
            </ul></li>
        <?php endforeach ?>
    <?php endif  ?>
</ul>
3
  • This doesn't answer my question...
    – Scott
    Commented Mar 14, 2012 at 17:11
  • I've added a demo of the idea, it's not using a walker, but I think it achieves what you want. Commented Mar 14, 2012 at 17:33
  • Sorry but this isn't recursive to suite more levels.
    – Scott
    Commented Mar 14, 2012 at 17:46
0

Considere use the argument "depth"

Example:

wp_list_pages( 'sort_column=menu_order&title_li=&child_of=' . $post->ID . '&echo=0&depth=1' 

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.