Skip to:
Content

BuddyPress.org

Ticket #4629: ticket-4629.002.patch

File ticket-4629.002.patch, 13.1 KB (added by DJPaul, 13 years ago)
  • bp-core/bp-core-classes.php

    class BP_Embed extends WP_Embed { 
    17731773                return $this->maybe_make_link( $url );
    17741774        }
    17751775}
     1776
     1777/**
     1778 * Create HTML list of BP nav items
     1779 *
     1780 * @since BuddyPress (1.7)
     1781 */
     1782class BP_Walker_Nav_Menu extends Walker_Nav_Menu {
     1783        /**
     1784         * @since BuddyPress (1.7)
     1785         * @var array
     1786         */
     1787        var $db_fields = array( 'id' => 'css_id', 'parent' => 'parent' );
     1788
     1789        /**
     1790         * @since BuddyPress (1.7)
     1791         * @var string
     1792         */
     1793        var $tree_type = array();
     1794
     1795        /**
     1796         * Display array of elements hierarchically.
     1797         *
     1798         * This method is almost identical to the version in {@link Walker::walk()}. The only change is on one line
     1799         * which has been commented. An IF was comparing 0 to a non-empty string which was preventing child elements
     1800         * being grouped under their parent menu element.
     1801         *
     1802         * This caused a problem for BuddyPress because our primary/secondary navigations doesn't have a unique numerical
     1803         * ID that describes a hierarchy (we use a slug). Obviously, WordPress Menus use Posts, and those have ID/post_parent.
     1804         *
     1805         * @param array $elements
     1806         * @param int $max_depth
     1807         * @return string
     1808         * @see Walker::walk()
     1809         * @since BuddyPress (1.7)
     1810         */
     1811        function walk( $elements, $max_depth ) {
     1812                $args   = array_slice( func_get_args(), 2 );
     1813                $output = '';
     1814
     1815                if ( $max_depth < -1 ) // invalid parameter
     1816                        return $output;
     1817
     1818                if ( empty( $elements ) ) // nothing to walk
     1819                        return $output;
     1820
     1821                $id_field     = $this->db_fields['id'];
     1822                $parent_field = $this->db_fields['parent'];
     1823
     1824                // flat display
     1825                if ( -1 == $max_depth ) {
     1826
     1827                        $empty_array = array();
     1828                        foreach ( $elements as $e )
     1829                                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
     1830
     1831                        return $output;
     1832                }
     1833
     1834                /*
     1835                 * need to display in hierarchical order
     1836                 * separate elements into two buckets: top level and children elements
     1837                 * children_elements is two dimensional array, eg.
     1838                 * children_elements[10][] contains all sub-elements whose parent is 10.
     1839                 */
     1840                $top_level_elements = array();
     1841                $children_elements  = array();
     1842
     1843                foreach ( $elements as $e ) {
     1844                        // BuddyPress: changed '==' to '==='. This is the only change from version in Walker::walk().
     1845                        if ( 0 === $e->$parent_field )
     1846                                $top_level_elements[] = $e;
     1847                        else
     1848                                $children_elements[$e->$parent_field][] = $e;
     1849                }
     1850
     1851                /*
     1852                 * when none of the elements is top level
     1853                 * assume the first one must be root of the sub elements
     1854                 */
     1855                if ( empty( $top_level_elements ) ) {
     1856
     1857                        $first              = array_slice( $elements, 0, 1 );
     1858                        $root               = $first[0];
     1859                        $top_level_elements = array();
     1860                        $children_elements  = array();
     1861
     1862                        foreach ( $elements as $e ) {
     1863                                if ( $root->$parent_field == $e->$parent_field )
     1864                                        $top_level_elements[] = $e;
     1865                                else
     1866                                        $children_elements[$e->$parent_field][] = $e;
     1867                        }
     1868                }
     1869
     1870                foreach ( $top_level_elements as $e )
     1871                        $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
     1872
     1873                /*
     1874                 * if we are displaying all levels, and remaining children_elements is not empty,
     1875                 * then we got orphans, which should be displayed regardless
     1876                 */
     1877                if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
     1878                        $empty_array = array();
     1879
     1880                        foreach ( $children_elements as $orphans )
     1881                                foreach ( $orphans as $op )
     1882                                        $this->display_element( $op, $empty_array, 1, 0, $args, $output );
     1883                 }
     1884
     1885                 return $output;
     1886        }
     1887
     1888        /**
     1889         * Displays the current <li> that we are on.
     1890         *
     1891         * @param string $output Passed by reference. Used to append additional content.
     1892         * @param object $item Menu item data object.
     1893         * @param int $depth Depth of menu item. Used for padding. Optional, defaults to 0.
     1894         * @param array $args Optional
     1895         * @param int $current_page Menu item ID. Optional.
     1896         * @since BuddyPress (1.7)
     1897         */
     1898        function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
     1899                // If we're someway down the tree, indent the HTML with the appropriate number of tabs
     1900                $indent = $depth ? str_repeat( "\t", $depth ) : '';
     1901
     1902                // Add HTML classes
     1903                $class_names = join( ' ', apply_filters( 'bp_nav_menu_css_class', array_filter( $item->class ), $item, $args ) );
     1904                $class_names = ! empty( $class_names ) ? ' class="' . esc_attr( $class_names ) . '"' : '';
     1905
     1906                // Add HTML ID
     1907                $id = sanitize_html_class( $item->css_id . '-personal-li' );  // Backpat with BP pre-1.7
     1908                $id = apply_filters( 'bp_nav_menu_item_id', $id, $item, $args );
     1909                $id = ! empty( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
     1910
     1911                // Opening tag; closing tag is handled in Walker_Nav_Menu::end_el().
     1912                $output .= $indent . '<li' . $id . $class_names . '>';
     1913
     1914                // Add href attribute
     1915                $attributes = ! empty( $item->link ) ? ' href="' . esc_attr( esc_url( $item->link ) ) . '"' : '';
     1916
     1917                // Construct the link
     1918                $item_output = $args->before;
     1919                $item_output .= '<a' . $attributes . '>';
     1920                $item_output .= $args->link_before . apply_filters( 'the_title', $item->name, 0 ) . $args->link_after;
     1921                $item_output .= '</a>';
     1922                $item_output .= $args->after;
     1923
     1924                // $output is byref
     1925                $output .= apply_filters( 'bp_walker_nav_menu_start_el', $item_output, $item, $depth, $args );
     1926        }
     1927}
  • bp-core/bp-core-template.php

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