Skip to:
Content

BuddyPress.org

Ticket #4629: ticket-4629.001.patch

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