0

In a Timber based Wordpress project, I need to add programaticly all Terms(with link) of a custom taxonomy(victim groups) in a TimberMenu as children of the menu point victims(a custom post type).

Is there an (elegant) way to do this?

Wordpress Version : 4.4.2 Timber Version: 0.22.5

=======UPDATE========

For example: in my taxonomy term (victim groups) I have the terms a,b,c,d,e

now I want to add a menu item called victim groups with the child items a,b,c,d and e

So that I can klick on any of a,b,c,d or e to get a page with all posts related to this term.

The customer isn't allowed to set menu items, so that I have to set them programmaticly and auto add all new terms of this taxonomy(victim groups) to it. cheers and thanks in advance bambamboole

bambamboole
  • 577
  • 10
  • 30
  • I'm having trouble understanding what you want to do. You want to add all terms in a taxonomy to a menu? Or just the terms related to a specific post? Can you show us an example of what you'd like this to look like? – Chris Herbert Apr 06 '16 at 18:55

1 Answers1

1

I normally do this kind of things through the wp_get_nav_menu_items filter. When I tried this first, it took me quite some time to get how I can mock up an existing WP_Post or WP_Term to be used as a nav menu item. You can’t just add the item itself, but you need to adapt it a little so that the nav item still links to the right destination. Also, if you just add menu items it can mess up your menu order. So we have to rebuild the menu array with our own menu order counter.

I have used the following combination of a helper function and variations of the wp_get_nav_menu_items filter in a couple of projects to quickly add new items to my menus, be it custom post types or taxonomies. It worked great so far. This approach should work whether you use the standard WP Nav Menu Walker or TimberMenu to display your menus in your theme.

The helper function

/**
 * Prepare a post or term object to be used as a WP nav menu item.
 *
 * @param string $type                  The type of the object added to the menu. Can be 'page',
 *                                      'category', 'taxonomy' or empty, assuming a custom post type
 * @param WP_Post|WP_Term $menu_post    The object you want to add that is converted
 *                                      to a menu item
 * @param int $menu_parent              The parent menu item you want to add the object to
 * @param int $menu_order_counter       The current menu order counter
 * @param bool $set_new_id              Whether to overwrite the current menu id. You normally want to
 *                                      do this, if you don’t want menu items to disappear randomly.
 * @return void
 */
function pre_setup_nav_menu_item( $type = '', &$menu_post, $menu_parent, $menu_order_counter, $set_new_id = true ) {
    $menu_post->menu_item_parent = $menu_parent;
    $menu_post->menu_order       = $menu_order_counter;
    $menu_post->post_type        = 'nav_menu_item';

    if ( 'page' == $type ) {
        $menu_post->object_id = $menu_post->ID;
        $menu_post->object    = 'page';
        $menu_post->type      = 'post_type';

    } else if ( 'category' == $type ) {
        $menu_post->object_id = $menu_post->term_id;
        $menu_post->object    = 'category';
        $menu_post->type      = 'taxonomy';

    } else if ( 'taxonomy' == $type ) {
        $menu_post->object_id = $menu_post->term_id;
        $menu_post->object    = $menu_post->taxonomy;
        $menu_post->type      = 'taxonomy';

    // Assuming a custom post type
    } else {
        // Use TimberPost if Timber exists
        if ( class_exists( 'Timber' ) ) {
            $menu_post = new TimberPost( $menu_post );
        }

        $menu_post->object_id = $menu_post->ID;
        $menu_post->object    = $type;
        $menu_post->type      = 'post_type';
    }

    /**
     * Create unique ID because in some cases the ID
     * will act as an array key. This way, no menu objects
     * should be overwritten.
     */
    if ( $set_new_id ) {
        $menu_post->ID = uniqid();
    }
}

The filter

We take all the existing menu items and loop over them. When the menu item "Victims" is found, we get all the Victim Group terms and add them as submenu items. To be able to find the right menu item, you would create a page "Victims" which you then add manually to your Menu. In the following filter, you will have to set the page id of the page "Victim" as well as the name with which you registered your custom taxonomy.

/**
 * Filter through nav menu items and add child items and anchor links accordingly
 */
add_filter( 'wp_get_nav_menu_items', function( $items, $menu, $args ) {
    /**
     * The page id of the page that was added manually to the menu
     * and should hold the custom taxonomy menu items.
     */
    $victim_page_id = 22;

    // Name of the custom taxonomy victim groups
    $victim_groups_tax_name = 'victimgroup';

    /**
     * Menus in Admin would also be affected if we wouldn’t
     * check if we’re on the frontend
     */
    if ( ! is_admin() ) {
        // Array to hold the newly built nav menu items array
        $new_items = array();

        // Integer to store custom menu order as we build up the new array
        $menu_order_counter = 1;

        /**
         * Loop through existing menu items and add them to custom menu
         */
        foreach ( $items as $item ) {
            // Add items in normal order
            $item->menu_order = $menu_order_counter;
            $new_items[] = $item;

            $menu_order_counter++;

            // Check for the menu item we want to add our submenu items to
            if ( (int) $item->object_id == $victim_page_id ) {
                // Victim Groups take the current menu item as a parent
                $menu_parent = $item->ID;

                // Get victim groups taxonomy terms
                $terms = Timber::get_terms( $victim_groups_tax_name, array(
                    // You probably want to hide empty taxonomies
                    'hide_empty' => true,
                ) );

                // Loop through terms found and add them as menu items
                foreach ( $terms as $term ) {
                    $term->post_title   = $term->name;
                    $term->post_parent  = $term->parent;

                    pre_setup_nav_menu_item( 'taxonomy', $term, $menu_parent, $menu_order_counter );
                    $term = new TimberTerm( $term );

                    $new_items[] = wp_setup_nav_menu_item( $term );

                    $menu_order_counter++;
                    unset( $term );
                }
            }
        }

        return $new_items;
    }

    return $items;
}, 10, 3);
Gchtr
  • 2,749
  • 2
  • 18
  • 28