0

I'm trying to build a sidebar menu displaying child pages of a grandparent page, his siblings and their childs, and keep those siblings and childs available while navigating through them.

I've been looking at different and similar posts at the forum, but so far I haven't had any luck with an exact solution or something I can tweak to achieve this.

This is my pages estructure:

  • Services
    • Service One
      • Service One About
      • Service One Sub-Services
        • Sub-service One A
        • Sub-service One B
        • Sub-service One C
    • Service Two
      • Service Two About
      • Service Two Sub-Services
        • Sub-service Two A
        • Sub-service Two B
        • Sub-service Two C

What I'm trying to do is:

If I'm in "Service One About", I should only show "Service One About", his siblings and its childs.

  • Service One
    • Service One About [current]
    • Service One Sub-Services
      • Sub-service One A
      • Sub-service One B
      • Sub-service One C

If I'm in "Service One Sub-Services", I should only show "Service One Sub-Services", his siblings and its childs.

  • Service One
    • Service One About
    • Service One Sub-Services [Current]
      • Sub-service One A
      • Sub-service One B
      • Sub-service One C

If I'm in "Sub-service One A", I should show his parent and uncle, and his siblings.

  • Service One
    • Service One About
    • Service One Sub-Services
      • Sub-service One A [current]
      • Sub-service One B
      • Sub-service One C

And so on.

That said, in case it's not clear: I wan't to exclude the "Service" grandparent, as well as the whole "Service Two" branch while I'm navigating through "Service One" and viceversa.

It is very important for me to control the output of each level because I have created a custom field on the pages to use it as a CSS class. For this I'm using Toolset Types & Views and I'm planning to print this as an <?php echo do_shortcode('[some-custom-field-shortcode]') ?> as shown on the example below.

Also, it would be great if I could add a class to the current menu item, so I could mark it as the current item.

Based on my "Sub-service One A" example above, this is how my output markup should look like:

<ul class="menu">
    <li><a href="#">Service One About</a></li>
    <li><a href="#">Service One Sub-Services</a>
        <ul class="sub-menu">
            <li class="current-menu-item"><a href="#"><span class="icon [some-custom-field-shortcode]"></span> <span class="text">Sub-service One A</span></a></li>
            <li><a href="#"><span class="icon [some-custom-field-shortcode]"></span> <span class="text">Sub-service One B</span></a></li>
            <li><a href="#"><span class="icon [some-custom-field-shortcode]"></span> <span class="text">Sub-service One C</span></a></li>
        </ul>
    </li>
</ul>

Could you please give me a hand with this? I've been really fighting to achieve this with Types & Views, but their forum doesn't seem to help (other users had asked similar questions and most of them just got frustrated and ended up using a plugin like this.

Thank you so much in advance! :)

3
  • 1
    The dinamic requeriments you need it is a very custom job that wp_list_pages can not handle as it is. The only way is defining a custom walker (see walker argument) to override the output or, due the high customization, make your own function. By the way, I think that the data structure you have make it harder; for example, what is logic that make "Service One About" a sister page of "Services Two Sub-Services"?. Maybe you can rethink about the data structure.
    – cybmeta
    Commented Dec 27, 2014 at 19:42
  • @cybmeta Thanks for your reply and thanks for pointing an error in what I said is my pages structure. When I wrote the whole question, I missed the parent page for each "About" and "Sub-services", which is of course, the name of the service itself "Service One" and "Service Two". I'm going to edit the question. About what I need to do: I really don't think it's that difficult. I have similar pieces of code retrieving similar structures, but also including the parent's siblings, which I do not want to show. I'm gonna update my question including some code examples as well. Thanks! Commented Dec 28, 2014 at 14:40
  • Now it is easier. Working on an answer.
    – cybmeta
    Commented Dec 28, 2014 at 17:49

1 Answer 1

1

Basically you want to display a menu of child pages of "Sevice One" if you are in any child page of "Service One", a menu of child pages of "Service Two" if you are in any chiild page of "Service Two", and so on.

This can be done with the child_of argument of wp_list_pages. We can fill this parameter dynamically using get_post_ancestors for current page and set the before last parent as the child_of parameter (the last parent would be "Services" and the before last would be "Service One" if you are in a page child of "Service One", "Service Two" if you are in a page child of "Service Two", and so on).

To include the <span> and execute the shortocodes in that place we can use link_before and link_after arguments.

For example:

function pages_menu() {

    if( !is_page() ) {
        return false;
    }

    $page_id = get_queried_object_id();
    $ancestors = get_post_ancestors($page_id);
    $ancestors_count = count($ancestors);
    if( $ancestors_count > 1 ) {

        //the last item in $ancestors will be the top parent page, that is "Services"
        //but we want the before top parent ("Service One", "Service Two", etc)
        $top_menu_page = $ancestors[$ancestors_count - 2];

    } else {
        //We are actually on one of our top menu pages ("Service One", "Service Two", etc)
        $top_menu_page = $page_id;
    }

    $args = array(
        'child_of'    => $top_menu_page,
        'link_before' => '<span class="icon '.do_shortcode('[some-custom-field-shortcode]').'"></span> <span class="text">',
        'link_after'  => '</span>',
    );
     wp_list_pages( $args );

}

Now you can use pages_menu() to print this dynamic menu on any page.

About the classes. Current page already has the current_page_item class as you need. Also, each page class attribute is filled with a complete set of classes representing the item, including page ID, classes for pages with children, with ancestors, parent/child of current page, etc. Inspect the output to make an idea.

(I don't kmow the exact context where this code will be used. It may needs adjustment to full fit to your needs.)

2
  • Thank you SO MUCH for your help and the whole explanation! This is precisely what I needed to do! You are awesome :) Thanks again! Commented Dec 29, 2014 at 14:37
  • You are wellcome. Glad I could help you.
    – cybmeta
    Commented Dec 29, 2014 at 16:08

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.