Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
11/09/2012 04:28:30 PM (13 years ago)
Author:
djpaul
Message:

Introduces bp_nav_menu(), which displays a merged navigation list from registered components. Fixes #4629.

BP has historically used bp_get_displayed_user_nav() and bp_get_options_nav() to render the navigation, and these menus have always been visually separate in the Default theme; either in columns before 1.2, and in rows since 1.2.

To provide more customisation for theme authors, and have both parts of the navigation displayed in the same block, this change introduces a merged menu function, with the parts from bp_get_options_nav nested appropriately under bp_get_displayed_user_nav.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bp-core/bp-core-template.php

    r6484 r6503  
    17431743    }
    17441744    add_filter( 'body_class', 'bp_get_the_body_class', 10, 2 );
     1745
     1746/**
     1747 * Sort BuddyPress nav menu items by their position property.
     1748 *
     1749 * This is an internal convenience function and it will probably be removed in a later release. Do not use.
     1750 *
     1751 * @access private
     1752 * @param array $a First item
     1753 * @param array $b Second item
     1754 * @return int Returns an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
     1755 * @since BuddyPress (1.7)
     1756 */
     1757function _bp_nav_menu_sort( $a, $b ) {
     1758    if ( $a["position"] == $b["position"] )
     1759        return 0;
     1760
     1761    else if ( $a["position"] < $b["position"] )
     1762        return -1;
     1763
     1764    else
     1765        return 1;
     1766}
     1767
     1768/**
     1769 * Get an array of all the items registered in the primary and secondary BuddyPress navigation menus
     1770 *
     1771 * @return array
     1772 * @since BuddyPress (1.7)
     1773 */
     1774function bp_get_nav_menu_items() {
     1775    $menus = $selected_menus = array();
     1776
     1777    // Get the second level menus
     1778    foreach ( (array) buddypress()->bp_options_nav as $parent_menu => $sub_menus ) {
     1779
     1780        // The root menu's ID is "xprofile", but the Profile submenus are using "profile". See BP_Core::setup_nav().
     1781        if ( 'profile' == $parent_menu )
     1782            $parent_menu = 'xprofile';
     1783
     1784        // Sort the items in this menu's navigation by their position property
     1785        $second_level_menus = (array) $sub_menus;
     1786        usort( $second_level_menus, '_bp_nav_menu_sort' );
     1787
     1788        // Iterate through the second level menus
     1789        foreach( $second_level_menus as $sub_nav ) {
     1790
     1791            // Skip items we don't have access to
     1792            if ( ! $sub_nav['user_has_access'] )
     1793                continue;
     1794
     1795            // Add this menu
     1796            $menu         = new stdClass;
     1797            $menu->class  = array();
     1798            $menu->css_id = $sub_nav['css_id'];
     1799            $menu->link   = $sub_nav['link'];
     1800            $menu->name   = $sub_nav['name'];
     1801            $menu->parent = $parent_menu;  // Associate this sub nav with a top-level menu
     1802
     1803            // If we're viewing this item's screen, record that we need to mark its parent menu to be selected
     1804            if ( $sub_nav['slug'] == bp_current_action() ) {
     1805                $menu->class      = array( 'current-menu-item' );
     1806                $selected_menus[] = $parent_menu;
     1807            }
     1808
     1809            $menus[] = $menu;
     1810        }
     1811    }
     1812
     1813    // Get the top-level menu parts (Friends, Groups, etc) and sort by their position property
     1814    $top_level_menus = (array) buddypress()->bp_nav;
     1815    usort( $top_level_menus, '_bp_nav_menu_sort' );
     1816
     1817    // Iterate through the top-level menus
     1818    foreach ( $top_level_menus as $nav ) {
     1819
     1820        // Skip items marked as user-specific if you're not on your own profile
     1821        if ( ! $nav['show_for_displayed_user'] && ! bp_is_my_profile() )
     1822            continue;
     1823
     1824        // Get the correct menu link. See http://buddypress.trac.wordpress.org/ticket/4624
     1825        $link = bp_loggedin_user_domain() ? str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $nav['link'] ) : trailingslashit( bp_displayed_user_domain() . $nav['link'] );
     1826
     1827        // Add this menu
     1828        $menu         = new stdClass;
     1829        $menu->class  = array();
     1830        $menu->css_id = $nav['css_id'];
     1831        $menu->link   = $link;
     1832        $menu->name   = $nav['name'];
     1833        $menu->parent = 0;
     1834
     1835        // Check if we need to mark this menu as selected
     1836        if ( in_array( $nav['css_id'], $selected_menus ) )
     1837            $menu->class = array( 'current-menu-parent' );
     1838
     1839        $menus[] = $menu;
     1840    }
     1841
     1842    return apply_filters( 'bp_get_nav_menu_items', $menus );
     1843}
     1844
     1845/**
     1846 * Displays a navigation menu.
     1847 *
     1848 * @param string|array $args Optional arguments:
     1849 *  before - Text before the link text.
     1850 *  container - Whether to wrap the ul, and what to wrap it with. Defaults to div.
     1851 *  container_class - The class that is applied to the container. Defaults to 'menu-bp-container'.
     1852 *  container_id - The ID that is applied to the container. Defaults to blank.
     1853 *  depth - How many levels of the hierarchy are to be included. 0 means all. Defaults to 0.
     1854 *  echo - Whether to echo the menu or return it. Defaults to echo.
     1855 *  fallback_cb - If the menu doesn't exists, a callback function will fire. Defaults to false (no fallback).
     1856 *  items_wrap - How the list items should be wrapped. Defaults to a ul with an id and class. Uses printf() format with numbered placeholders.
     1857 *  link_after - Text after the link.
     1858 *  link_before - Text before the link.
     1859 *  menu_class - CSS class to use for the ul element which forms the menu. Defaults to 'menu'.
     1860 *  menu_id - The ID that is applied to the ul element which forms the menu. Defaults to 'menu-bp', incremented.
     1861 *  walker - Allows a custom walker to be specified. Defaults to 'BP_Walker_Nav_Menu'.
     1862 * @since BuddyPress (1.7)
     1863 */
     1864function bp_nav_menu( $args = array() ) {
     1865    static $menu_id_slugs = array();
     1866
     1867    $defaults = array(
     1868        'after'           => '',
     1869        'before'          => '',
     1870        'container'       => 'div',
     1871        'container_class' => '',
     1872        'container_id'    => '',
     1873        'depth'           => 0,
     1874        'echo'            => true,
     1875        'fallback_cb'     => false,
     1876        'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>',
     1877        'link_after'      => '',
     1878        'link_before'     => '',
     1879        'menu_class'      => 'menu',
     1880        'menu_id'         => '',
     1881        'walker'          => '',
     1882    );
     1883    $args = wp_parse_args( $args, $defaults );
     1884    $args = apply_filters( 'bp_nav_menu_args', $args );
     1885    $args = (object) $args;
     1886
     1887    $items = $nav_menu = '';
     1888    $show_container = false;
     1889
     1890    // Create custom walker if one wasn't set
     1891    if ( empty( $args->walker ) )
     1892        $args->walker = new BP_Walker_Nav_Menu;
     1893
     1894    // Sanitise values for class and ID
     1895    $args->container_class = sanitize_html_class( $args->container_class );
     1896    $args->container_id    = sanitize_html_class( $args->container_id );
     1897
     1898    // Whether to wrap the ul, and what to wrap it with
     1899    if ( $args->container ) {
     1900        $allowed_tags = apply_filters( 'wp_nav_menu_container_allowedtags', array( 'div', 'nav', ) );
     1901
     1902        if ( in_array( $args->container, $allowed_tags ) ) {
     1903            $show_container = true;
     1904
     1905            $class     = $args->container_class ? ' class="' . esc_attr( $args->container_class ) . '"' : ' class="menu-bp-container"';
     1906            $id        = $args->container_id    ? ' id="' . esc_attr( $args->container_id ) . '"'       : '';
     1907            $nav_menu .= '<' . $args->container . $id . $class . '>';
     1908        }
     1909    }
     1910
     1911    // Get the BuddyPress menu items
     1912    $menu_items = apply_filters( 'bp_nav_menu_objects', bp_get_nav_menu_items(), $args );
     1913    $items      = walk_nav_menu_tree( $menu_items, $args->depth, $args );
     1914    unset( $menu_items );
     1915
     1916    // Set the ID that is applied to the ul element which forms the menu.
     1917    if ( ! empty( $args->menu_id ) ) {
     1918        $wrap_id = $args->menu_id;
     1919
     1920    } else {
     1921        $wrap_id = 'menu-bp';
     1922
     1923        // If a specific ID wasn't requested, and there are multiple menus on the same screen, make sure the autogenerated ID is unique
     1924        while ( in_array( $wrap_id, $menu_id_slugs ) ) {
     1925            if ( preg_match( '#-(\d+)$#', $wrap_id, $matches ) )
     1926                $wrap_id = preg_replace('#-(\d+)$#', '-' . ++$matches[1], $wrap_id );
     1927            else
     1928                $wrap_id = $wrap_id . '-1';
     1929        }
     1930    }
     1931    $menu_id_slugs[] = $wrap_id;
     1932
     1933    // Allow plugins to hook into the menu to add their own <li>'s
     1934    $items = apply_filters( 'bp_nav_menu_items', $items, $args );
     1935
     1936    // Build the output
     1937    $wrap_class  = $args->menu_class ? $args->menu_class : '';
     1938    $nav_menu   .= sprintf( $args->items_wrap, esc_attr( $wrap_id ), esc_attr( $wrap_class ), $items );
     1939    unset( $items );
     1940
     1941    // If we've wrapped the ul, close it
     1942    if ( $show_container )
     1943        $nav_menu .= '</' . $args->container . '>';
     1944
     1945    // Final chance to modify output
     1946    $nav_menu = apply_filters( 'bp_nav_menu', $nav_menu, $args );
     1947
     1948    if ( $args->echo )
     1949        echo $nav_menu;
     1950    else
     1951        return $nav_menu;
     1952}
Note: See TracChangeset for help on using the changeset viewer.