Skip to:
Content

BuddyPress.org

Ticket #6534: 6534.item_id.patch

File 6534.item_id.patch, 29.7 KB (added by imath, 9 years ago)
  • src/bp-core/bp-core-classes.php

    diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php
    index 41be065..0a65aa1 100644
    require dirname( __FILE__ ) . '/classes/class-bp-recursive-query.php'; 
    2323require dirname( __FILE__ ) . '/classes/class-bp-media-extractor.php';
    2424require dirname( __FILE__ ) . '/classes/class-bp-attachment.php';
    2525require dirname( __FILE__ ) . '/classes/class-bp-attachment-avatar.php';
     26require dirname( __FILE__ ) . '/classes/class-bp-single-item-navigation.php';
  • src/bp-core/bp-core-filters.php

    diff --git src/bp-core/bp-core-filters.php src/bp-core/bp-core-filters.php
    index b5e857a..55fb3d2 100644
    function bp_modify_page_title( $title = '', $sep = '»', $seplocation = 'ri 
    731731
    732732        // A single item from a component other than groups
    733733        } elseif ( bp_is_single_item() ) {
    734                 $title_parts = array( $bp->bp_options_title, $bp->bp_options_nav[ bp_current_item() ][ bp_current_action() ]['name'] );
     734                if ( isset( $bp->{$bp->current_component}->nav->main[ bp_get_single_item_id() ] ) ) {
     735                        $component_nav_section = '';
     736
     737                        // Get the component nav section name
     738                        foreach ( $bp->{$bp->current_component}->nav->main[ bp_get_single_item_id() ] as $component_nav_item ) {
     739                                if ( bp_current_action() !== $component_nav_item['slug'] ) {
     740                                        continue;
     741                                }
     742
     743                                $component_nav_section = $component_nav_item['name'];
     744                        }
     745
     746                        $title_parts = array( $bp->bp_options_title, $component_nav_section );
     747                } else {
     748                        $title_parts = array( $bp->bp_options_title, $bp->bp_options_nav[ bp_current_item() ][ bp_current_action() ]['name'] );
     749                }
    735750
    736751        // An index or directory
    737752        } elseif ( bp_is_directory() ) {
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index 55449bf..5a47335 100644
    function bp_update_is_item_mod( $is_item_mod = false, $component = '' ) { 
    19691969}
    19701970
    19711971/**
     1972 * Set the "single_item_id" global.
     1973 *
     1974 * @since  BuddyPress (2.4.0)
     1975 *
     1976 * @param  int $single_item_id the single item id (eg: a group id or a blog id)
     1977 * @param  string  $component  Optional. Component name. Default: the current
     1978 */
     1979function bp_update_single_item_id( $single_item_id = 0, $component = '' ) {
     1980        if ( empty( $component ) ) {
     1981                $component = bp_current_component();
     1982        }
     1983
     1984        /**
     1985         * Filters the "single_item_id" global value.
     1986         *
     1987         * @since BuddyPress (2.4.0)
     1988         *
     1989         * @param int   $single_item_id the current single item id being displayed
     1990         * @param string $component   Component name. Default: the current component.
     1991         */
     1992        buddypress()->single_item_id = (int) apply_filters( 'bp_update_single_item_id', $single_item_id, $component );
     1993}
     1994
     1995/**
     1996 * Get the "single_item_id" global.
     1997 *
     1998 * @since  BuddyPress (2.4.0)
     1999 *
     2000 * @return int the current single item id being displayed
     2001 */
     2002function bp_get_single_item_id() {
     2003        $bp     = buddypress();
     2004        $retval = 0;
     2005
     2006        if ( isset( $bp->single_item_id ) ) {
     2007                $retval = $bp->single_item_id;
     2008        }
     2009
     2010        return $retval;
     2011}
     2012
     2013/**
    19722014 * Trigger a 404.
    19732015 *
    19742016 * @since BuddyPress (1.5.0)
  • src/bp-core/bp-core-template.php

    diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php
    index f1c833a..6c192b5 100644
    function bp_get_options_nav( $parent_slug = '' ) { 
    8787}
    8888
    8989/**
     90 * Output a component's single item main nav
     91 *
     92 * @since BuddyPress (2.4.0)
     93 *
     94 * @param  string $component the component id
     95 */
     96function bp_single_item_main_nav( $component = '' ) {
     97        $bp = buddypress();
     98
     99        if ( empty( $component ) ) {
     100                $component = bp_current_component();
     101        }
     102
     103        if ( ! isset( $bp->{$component}->nav ) || ! is_a( $bp->{$component}->nav, 'BP_Single_Item_Navigation' ) ) {
     104                return;
     105        }
     106
     107        $bp->{$component}->nav->display_main_nav();
     108}
     109
     110/**
     111 * Output a component's single item options nav
     112 *
     113 * @since BuddyPress (2.4.0)
     114 *
     115 * @param  string $component the component id
     116 */
     117function bp_single_item_sub_nav( $component = '' ) {
     118        $bp = buddypress();
     119
     120        if ( empty( $component ) ) {
     121                $component = bp_current_component();
     122        }
     123
     124        if ( ! bp_is_single_item() || ! isset( $bp->{$component}->nav ) || ! is_a( $bp->{$component}->nav, 'BP_Single_Item_Navigation' ) ) {
     125                return;
     126        }
     127
     128        $bp->{$component}->nav->display_sub_nav();
     129}
     130
     131/**
    90132 * Get the 'bp_options_title' property from the BP global.
    91133 *
    92134 * Not currently used in BuddyPress.
  • src/bp-core/classes/class-bp-single-item-navigation.php

    diff --git src/bp-core/classes/class-bp-single-item-navigation.php src/bp-core/classes/class-bp-single-item-navigation.php
    index e69de29..82b1929 100644
     
     1<?php
     2/**
     3 * Core component classes.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 */
     8
     9// Exit if accessed directly
     10defined( 'ABSPATH' ) || exit;
     11
     12/**
     13 * API to create a component's single item navigation.
     14 *
     15 * @since BuddyPress (2.4.0)
     16 */
     17class BP_Single_Item_Navigation {
     18
     19        /**
     20         * The single item main nav
     21         *
     22         * @since BuddyPress (2.4.0)
     23         * @var array
     24         */
     25        public $main = array();
     26
     27        /**
     28         * The single item sub nav
     29         *
     30         * @since BuddyPress (2.4.0)
     31         * @var array
     32         */
     33        public $sub  = array();
     34
     35        /**
     36         * The single item object
     37         *
     38         * @since BuddyPress (2.4.0)
     39         * @var object
     40         */
     41        public $single_item  = null;
     42
     43        /**
     44         * The default args to be merged with the
     45         * ones passed to the constructor
     46         *
     47         * @since BuddyPress (2.4.0)
     48         * @var array
     49         */
     50        protected $default_args = array(
     51                'component_id'       => '',
     52                'component_slug'     => '',
     53                'single_item_name'   => '',
     54                'single_item_object' => null,
     55        );
     56
     57        /**
     58         * Constructor
     59         *
     60         * @since BuddyPress (2.4.0)
     61         *
     62         * @param array $args {
     63         *     Array of arguments.
     64         *     @type string     $component_id String describing the component id (eg: blogs, groups...).
     65         *     @type string     $component_slug The root slug of the component (eg: blogs, sites, groups...)
     66         *     @type string     $single_item_name Required. The single item name (eg: blog, group...)
     67         *     @type object|int $single_item_object Required. The single item object (eg: BP_Blogs_Blog) or ID
     68         * }
     69         */
     70        public function __construct( $args = array() ) {
     71                if ( empty( $args['single_item_name'] ) ) {
     72                        return false;
     73                }
     74
     75                // Merge args
     76                $params = wp_parse_args( $args, $this->default_args, $args['single_item_name'] . '_single_item_nav_params' );
     77
     78                foreach ( $params as $key => $param ) {
     79                        // Sanitize slug
     80                        if ( 'component_slug' === $key ) {
     81                                $this->{$key} = sanitize_title( $param );
     82
     83                        // Additional checks will happen later for the $single_item_object
     84                        } elseif ( 'single_item_object' === $key ) {
     85                                $this->{$key} = $param;
     86
     87                        // Sanitize other keys
     88                        } else {
     89                                $this->{$key} = sanitize_key( $param );
     90                        }
     91                }
     92
     93                // Use the current component as a fallback
     94                if ( empty( $this->component_id ) ) {
     95                        $this->component_id = bp_current_component();
     96                }
     97
     98                // Use the component root slug as a fallback
     99                if ( empty( $this->component_slug ) && is_callable( 'bp_get_' . $this->component_id . '_root_slug' ) ) {
     100                        $this->component_slug = call_user_func( 'bp_get_' . $this->component_id . '_root_slug' );
     101                }
     102
     103                // Get the item we're building the nav for
     104                if ( is_object( $this->single_item_object ) && ! empty( $this->single_item_object->slug ) ) {
     105                        $this->single_item = $this->single_item_object;
     106
     107                // Try to build it using it's ID
     108                } elseif ( is_numeric( $this->single_item_object ) ) {
     109                        /**
     110                         * item id key is {single_item_name}_id
     111                         *
     112                         * eg: blog_id or group_id
     113                         */
     114                        $objet_args = array(
     115                                $this->single_item_name . '_id' => $this->single_item_object,
     116                                'populate_extras'               => false,
     117                        );
     118                        /**
     119                         * The callback name is: {component_id}_get_{single_item_name}
     120                         *
     121                         * eg: blogs_get_blog() or groups_get_group()
     122                         */
     123                        $this->single_item = call_user_func_array( $this->component_id . '_get_' . $this->single_item_object, array( $objet_args ) );
     124                }
     125
     126                // Unset the temporary param
     127                unset( $this->single_item_object );
     128        }
     129
     130        /**
     131         * Setup the single item navigation
     132         *
     133         * @since BuddyPress (2.4.0)
     134         *
     135         * @param  array  $main_nav list of associative arrays containing the nav items params
     136         * @param  array  $sub_nav  list of associative arrays containing the sub nav items params
     137         */
     138        public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
     139                // Bail if the component slug or the component id are not set
     140                if ( ! $this->component_slug || ! $this->component_id ) {
     141                        return false;
     142                }
     143
     144                // No sub nav items without a main nav item
     145                if ( ! empty( $main_nav ) ) {
     146                        foreach( (array) $main_nav as $item ) {
     147                                $this->new_main_nav_item( $item );
     148                        }
     149
     150                        // Sub nav items are not required
     151                        if ( ! empty( $sub_nav ) ) {
     152                                foreach( (array) $sub_nav as $sub_item ) {
     153                                        $this->new_sub_nav_item( $sub_item );
     154                                }
     155                        }
     156                }
     157
     158                /**
     159                 * Fires at the end of the setup_nav method inside BP_Single_Item_Navigation.
     160                 *
     161                 * This is a dynamic hook that is based on the component string ID.
     162                 *
     163                 * @since BuddyPress (2.4.0)
     164                 */
     165                do_action( 'bp_' . $this->component_id . '_single_item_setup_nav' );
     166        }
     167
     168        /**
     169         * Add a new nav item to main nav
     170         *
     171         * @since BuddyPress (2.4.0)
     172         *
     173         * @param  array  $args associative array containing the item params
     174         */
     175        public function new_main_nav_item( $args = array() ) {
     176                // Bail if the component slug, the component id or the single item are not set
     177                if ( ! $this->component_slug || ! $this->component_id || empty( $this->single_item->item_id ) ) {
     178                        return false;
     179                }
     180
     181                // Get BuddyPress instance
     182                $bp = buddypress();
     183
     184                $slug = false;
     185                if ( ! empty( $args['slug'] ) ) {
     186                        $slug = $args['slug'];
     187                }
     188
     189                $item = bp_parse_args( $args, array(
     190                        'name'                    => false, // Display name for the nav item
     191                        'slug'                    => false, // URL slug for the nav item
     192                        'item_css_id'             => false, // The CSS ID to apply to the HTML of the nav item
     193                        'item_admin_only'         => false, // Can only item admins see this nav item?
     194                        'position'                => 99,    // Index of where this nav item should be positioned
     195                        'screen_function'         => false, // The name of the function to run when clicked
     196                        'default_subnav_slug'     => false  // The slug of the default subnav item to select when clicked
     197                ), $this->single_item_name . '_main_nav_item_' . $slug );
     198
     199                // If we don't have the required info we need, don't create this nav item
     200                if ( empty( $item['name'] ) || empty( $item['slug'] ) || empty( $item['screen_function'] ) ) {
     201                        return false;
     202                }
     203
     204                // If this is for site admins only and the user is not one, don't create the subnav item
     205                if ( ! empty( $item['item_admin_only'] ) && ! bp_is_item_admin() ) {
     206                        return false;
     207                }
     208
     209                if ( empty( $item['item_css_id'] ) ) {
     210                        $item['item_css_id'] = $item['slug'];
     211                }
     212
     213                /**
     214                 * By default a Link is composed by:
     215                 * 1. the root domain          eg: http://site.url
     216                 * 2. the component root slug  eg: sites
     217                 * 3. the current item slug    eg: blog_slug
     218                 * 4. the nav item slug        eg: home
     219                 */
     220                $link = bp_get_root_domain() . '/' . $this->component_slug . '/' . bp_current_item() . '/' . $item['slug'];
     221
     222                /**
     223                 * The component's single item can provide a specific method to build the item permalink
     224                 *
     225                 * eg: bp_get_group_permalink()
     226                 */
     227                if ( method_exists( $bp->{$this->component_id}, 'get_item_permalink' ) ) {
     228                        $link = $bp->{$this->component_id}->get_item_permalink( $this->single_item );
     229                        $link = trailingslashit( $link ) . $item['slug'];
     230                }
     231
     232                // Catch the link for a later use
     233                $this->single_item->parent_url = trailingslashit( $link );
     234
     235                $this->main[ $this->single_item->item_id ][ $item['slug'] ] = array(
     236                        'name'                    => $item['name'],
     237                        'slug'                    => $item['slug'],
     238                        'link'                    => $this->single_item->parent_url,
     239                        'css_id'                  => $item['item_css_id'],
     240                        'position'                => $item['position'],
     241                        'screen_function'         => &$item['screen_function'],
     242                        'default_subnav_slug'     => $item['default_subnav_slug']
     243                );
     244
     245                /**
     246                 * If this condition is true, this means the url looks like
     247                 * http://site.url/sites/blog_slug/home
     248                 */
     249                if ( bp_is_current_action( $item['slug'] ) ) {
     250                        /**
     251                         * If the default subnav match the first action variable move all left
     252                         */
     253                        if ( ! empty( $item['default_subnav_slug'] ) && bp_is_action_variable( $item['default_subnav_slug'], 0 ) && ! bp_action_variable( 1 ) ) {
     254                                unset( $bp->canonical_stack['action_variables'][0] );
     255
     256                        // No action variable it's the root of the nav
     257                        } elseif ( ! bp_action_variable( 0 ) ) {
     258
     259                                // Add our screen hook if screen function is callable
     260                                if ( is_callable( $item['screen_function'] ) ) {
     261                                        add_action( 'bp_screens', $item['screen_function'], 3 );
     262                                }
     263
     264                                if ( ! empty( $item['default_subnav_slug'] ) ) {
     265                                        /**
     266                                         * Filters the component's single nav default subnav item.
     267                                         *
     268                                         * @since BuddyPress (2.4.0)
     269                                         *
     270                                         * @param string $default_subnav_slug The slug of the default subnav item
     271                                         *                                    to select when clicked.
     272                                         * @param array  $r                   Parsed arguments for the nav item.
     273                                         */
     274                                        $bp->current_action = apply_filters( 'bp_single_item_default_subnav', $item['default_subnav_slug'], $item );
     275                                }
     276                        }
     277                }
     278        }
     279
     280        /**
     281         * Add a new sub nav item to sub nav
     282         *
     283         * @since BuddyPress (2.4.0)
     284         *
     285         * @param  array  $args associative array containing the sub item params
     286         */
     287        public function new_sub_nav_item( $args = array() ) {
     288                // Bail if the component slug, the component id or the single item are not set
     289                if ( ! $this->component_slug || ! $this->component_id || empty( $this->single_item->item_id ) ) {
     290                        return false;
     291                }
     292
     293                $slug = false;
     294                if ( ! empty( $args['slug'] ) ) {
     295                        $slug = $args['slug'];
     296                }
     297
     298                $sub_item = bp_parse_args( $args, array(
     299                        'name'              => false, // Display name for the nav item
     300                        'slug'              => false, // URL slug for the nav item
     301                        'parent_slug'       => false, // URL slug of the parent nav item
     302                        'parent_url'        => false, // URL of the parent item
     303                        'item_css_id'       => false, // The CSS ID to apply to the HTML of the nav item
     304                        'user_has_access'   => true,  // Can the logged in user see this nav item?
     305                        'no_access_url'     => '',
     306                        'item_admin_only'   => false, // Can only item admins see this nav item?
     307                        'position'          => 90,    // Index of where this nav item should be positioned
     308                        'screen_function'   => false, // The name of the function to run when clicked
     309                        'link'              => '',    // The link for the subnav item; optional, not usually required.
     310                        'show_in_admin_bar' => false, // Show the Manage link in the current group's "Edit" Admin Bar menu
     311                ), $this->single_item_name . '_sub_nav_item_' . $slug );
     312
     313
     314                // If we don't have the required info we need, don't create this subnav item
     315                if ( empty( $sub_item['name'] ) || empty( $sub_item['slug'] ) || empty( $sub_item['parent_slug'] ) || empty( $sub_item['screen_function'] ) ) {
     316                        return false;
     317                }
     318
     319                // Use the parent url previously built in BP_Single_Item_Navigation->new_main_nav_item() if not set in arguments
     320                if ( empty( $sub_item['parent_url'] ) && isset( $this->single_item->parent_url ) ) {
     321                        $sub_item['parent_url'] = $this->single_item->parent_url;
     322                }
     323
     324                // If this is for site admins only and the user is not one, don't create the subnav item
     325                if ( ! empty( $sub_item['item_admin_only'] ) && ! bp_is_item_admin() ) {
     326                        return false;
     327                }
     328
     329                if ( empty( $sub_item['link'] ) ) {
     330                        $sub_item['link'] = trailingslashit( $sub_item['parent_url'] . $sub_item['slug'] );
     331
     332                        // If this sub item is the default for its parent, skip the slug
     333                        if ( $sub_item['slug'] === $this->main[ $this->single_item->item_id ][ $sub_item['parent_slug'] ]['default_subnav_slug'] ) {
     334                                $sub_item['link'] = trailingslashit( $sub_item['parent_url'] );
     335                        }
     336                }
     337
     338                if ( empty( $sub_item['item_css_id'] ) ) {
     339                        $sub_item['item_css_id'] = $sub_item['slug'];
     340                }
     341
     342                $this->sub[ $this->single_item->item_id ][ $sub_item['parent_slug'] ][ $sub_item['slug'] ] = array(
     343                        'name'              => $sub_item['name'],
     344                        'link'              => $sub_item['link'],
     345                        'slug'              => $sub_item['slug'],
     346                        'css_id'            => $sub_item['item_css_id'],
     347                        'position'          => $sub_item['position'],
     348                        'user_has_access'   => $sub_item['user_has_access'],
     349                        'no_access_url'     => $sub_item['no_access_url'],
     350                        'screen_function'   => &$sub_item['screen_function'],
     351                        'show_in_admin_bar' => (bool) $sub_item['show_in_admin_bar'],
     352                );
     353
     354                if ( ! bp_is_current_component( $this->component_id ) && ! bp_is_current_action( $sub_item['parent_slug'] ) ) {
     355                        return false;
     356                }
     357
     358                if ( bp_action_variable( 0 ) && bp_is_action_variable( $sub_item['slug'], 0 ) ) {
     359
     360                        $hooked = bp_core_maybe_hook_new_subnav_screen_function( $this->sub[ $this->single_item->item_id ][ $sub_item['parent_slug'] ][ $sub_item['slug'] ] );
     361
     362                        // If redirect args have been returned, perform the redirect now
     363                        if ( ! empty( $hooked['status'] ) && 'failure' === $hooked['status'] && isset( $hooked['redirect_args'] ) ) {
     364                                bp_core_no_access( $hooked['redirect_args'] );
     365                        }
     366                }
     367        }
     368
     369        /**
     370         * Sort the main nav items and output the main nav.
     371         *
     372         * @since BuddyPress (2.4.0)
     373         *
     374         * @return HTML output
     375         */
     376        public function display_main_nav() {
     377                // Bail if the component slug, the component id or the single item id are not set
     378                if ( ! $this->component_slug || ! $this->component_id || empty( $this->single_item->item_id ) ) {
     379                        return false;
     380                }
     381
     382                // Sort the main nav just before it's displayed
     383                $main_nav = bp_sort_by_key( $this->main[ $this->single_item->item_id ], 'position', 'num' );
     384
     385                // Loop throw each nav item
     386                foreach ( (array) $main_nav as $main_nav_item ) {
     387                        // Defaults to none
     388                        $selected = '';
     389
     390                        if ( bp_is_current_action( $main_nav_item['slug'] ) ) {
     391                                $selected = ' class="current selected"';
     392                        }
     393
     394                        /**
     395                         * Filters the component's "main nav", the first-level single item navigation menu.
     396                         *
     397                         * This is a dynamic filter that is dependent on the component's single item and the provided css_id value.
     398                         *
     399                         * @since BuddyPress (2.4.0)
     400                         *
     401                         * @param string $value         HTML list item for the submenu item.
     402                         * @param array  $subnav_item   Main nav array item being displayed.
     403                         */
     404                        echo apply_filters_ref_array( 'bp_' . $this->single_item_name . '_main_nav_' . $main_nav_item['css_id'], array( '<li id="' . esc_attr( $main_nav_item['css_id'] ) . '-' . esc_attr( $this->component_id ) . '-li" ' . $selected . '><a id="' . esc_attr( $this->single_item_name ) . '-' . esc_attr( $main_nav_item['slug'] ) . '" href="' . esc_url( $main_nav_item['link'] ) . '">' . $main_nav_item['name'] . '</a></li>', &$main_nav_item ) );
     405                }
     406        }
     407
     408        /**
     409         * Sort the sub nav items and output the sub nav
     410         *
     411         * @since BuddyPress (2.4.0)
     412         *
     413         * @return HTML output
     414         */
     415        public function display_sub_nav() {
     416                // Bail if the component slug or the component id are not set
     417                if ( ! $this->component_slug || ! $this->component_id || empty( $this->single_item->item_id ) ) {
     418                        return false;
     419                }
     420
     421                $the_index = bp_current_action();
     422
     423                if ( bp_action_variable( 0 ) ) {
     424                        $selected_item = bp_action_variable( 0 );
     425                } else {
     426                        $selected_item = $the_index;
     427                }
     428
     429                if ( empty( $this->sub[ $this->single_item->item_id ][ $the_index ] ) ) {
     430                        return;
     431                }
     432
     433                // Sort the main nav just before it's displayed
     434                $sub_nav = bp_sort_by_key( $this->sub[ $this->single_item->item_id ][ $the_index ], 'position', 'num' );
     435
     436                // Loop throw each nav item
     437                foreach ( (array) $sub_nav as $sub_nav_item ) {
     438
     439                        if ( empty( $sub_nav_item['user_has_access'] ) ) {
     440                                continue;
     441                        }
     442
     443                        // If the current action or an action variable matches the nav item id, then add a highlight CSS class.
     444                        if ( $sub_nav_item['slug'] === $selected_item ) {
     445                                $selected = ' class="current selected"';
     446                        } else {
     447                                $selected = '';
     448                        }
     449
     450                        /**
     451                         * Filters the component's "single nav", the secondary-level single item navigation menu.
     452                         *
     453                         * This is a dynamic filter that is dependent on the component's id and the provided css_id value.
     454                         *
     455                         * @since BuddyPress (2.4.0)
     456                         *
     457                         * @param string $value         HTML list item for the submenu item.
     458                         * @param array  $subnav_item   Submenu array item being displayed.
     459                         * @param string $selected_item Current action.
     460                         */
     461                        echo apply_filters( 'bp_' . $this->single_item_name . '_single_subnav_' . $sub_nav_item['css_id'], '<li id="' . esc_attr( $sub_nav_item['css_id'] . '-' . $this->component_id . '-' . $this->single_item_name . '-li' ) . '" ' . $selected . '><a id="' . esc_attr( $sub_nav_item['css_id'] ) . '" href="' . esc_url( $sub_nav_item['link'] ) . '">' . $sub_nav_item['name'] . '</a></li>', $sub_nav_item, $selected_item );
     462                }
     463        }
     464
     465        /**
     466         * Get the sub nav items for the provided parent slug
     467         *
     468         * @since BuddyPress (2.4.0)
     469         *
     470         * @param  string $parent_slug the main nav parent slug
     471         * @return HTML   output
     472         */
     473        public function get_sub_nav_by_parent_slug( $parent_slug = '' ) {
     474                if ( empty( $parent_slug ) || empty( $this->single_item->item_id ) || empty( $this->sub[ $this->single_item->item_id ][ $parent_slug ] ) ) {
     475                        return false;
     476                }
     477
     478                // Sort the sub nav items
     479                $sub_nav_items = bp_sort_by_key( $this->sub[ $this->single_item->item_id ][ $parent_slug ], 'position', 'num' );
     480
     481                return $sub_nav_items;
     482        }
     483
     484        /**
     485         * Remove a main nav item for component's single item
     486         *
     487         * @since BuddyPress (2.4.0)
     488         *
     489         * @param  string $component        the component id
     490         * @param  string $main_nav_item_id the main nav item id
     491         * @return bool                     true if the main nav was removed, false otherwise
     492         */
     493        public static function remove_main_nav_item( $component = '', $item_id = 0, $main_nav_item_id = '' ) {
     494                $bp = buddypress();
     495
     496                if ( empty( $component ) || empty( $main_nav_item_id ) || ! isset( $bp->{$component}->nav->main[ $item_id ][ $main_nav_item_id ] ) ) {
     497                        return false;
     498                }
     499
     500                // Unset sub_nav items for this nav item
     501                if ( isset( $bp->{$component}->nav->sub[ $item_id ][ $main_nav_item_id ] ) && is_array( $bp->{$component}->nav->sub[ $item_id ][ $main_nav_item_id ] ) ) {
     502                        foreach( (array) $bp->{$component}->nav->sub[ $item_id ][ $main_nav_item_id ] as $sub_nav_item ) {
     503                                self::remove_sub_nav_item( $component, $item_id, $main_nav_item_id, $sub_nav_item['slug'] );
     504                        }
     505                }
     506
     507                $screen_function = false;
     508                if ( isset( $bp->{$component}->nav->main[ $item_id ][ $main_nav_item_id ]['screen_function'] ) ) {
     509                        $screen_function = $bp->{$component}->nav->main[ $item_id ][ $main_nav_item_id ]['screen_function'];
     510                }
     511
     512                if ( ! empty( $screen_function ) ) {
     513                        // Remove our screen hook if screen function is callable
     514                        if ( is_callable( $screen_function ) ) {
     515                                remove_action( 'bp_screens', $screen_function, 3 );
     516                        }
     517                }
     518
     519                unset( $bp->{$component}->nav->main[ $item_id ][ $main_nav_item_id ] );
     520                return true;
     521        }
     522
     523        /**
     524         * Remove a sub nav item for component's single item main nav
     525         *
     526         * @since BuddyPress (2.4.0)
     527         *
     528         * @param  string $component         the component id
     529         * @param  string $main_nav_item_id  the main nav item id
     530         * @param  string $sub_nav_item_slug the sub nav slug
     531         * @return bool                      true if the sub nav was removed, false otherwise
     532         */
     533        public static function remove_sub_nav_item( $component ='', $item_id = 0, $main_nav_item_id = '', $sub_nav_item_slug = '' ) {
     534                $bp = buddypress();
     535
     536                if ( empty( $component ) || empty( $main_nav_item_id ) || empty( $sub_nav_item_slug ) || ! isset( $bp->{$component}->nav->sub[ $item_id ][ $main_nav_item_id ][ $sub_nav_item_slug ] ) ) {
     537                        return false;
     538                }
     539
     540                $screen_function = false;
     541                if ( isset( $bp->{$component}->nav->sub[ $item_id ][ $main_nav_item_id ][ $sub_nav_item_slug ]['screen_function'] ) ) {
     542                        $screen_function = $bp->{$component}->nav->sub[ $item_id ][ $main_nav_item_id ][ $sub_nav_item_slug ]['screen_function'];
     543                }
     544
     545                if ( ! empty( $screen_function ) ) {
     546                        // Remove our screen hook if screen function is callable
     547                        if ( is_callable( $screen_function ) ) {
     548                                remove_action( 'bp_screens', $screen_function, 3 );
     549                        }
     550                }
     551
     552                unset( $bp->{$component}->nav->sub[ $item_id ][ $main_nav_item_id ][ $sub_nav_item_slug ] );
     553                return true;
     554        }
     555}
  • tests/phpunit/testcases/core/class-bp-single-item-navigation.php

    diff --git tests/phpunit/testcases/core/class-bp-single-item-navigation.php tests/phpunit/testcases/core/class-bp-single-item-navigation.php
    index e69de29..c6f8a76 100644
     
     1<?php
     2
     3/**
     4 * @group core
     5 * @group BP_Single_Item_Navigation
     6 * @group single_item_nav
     7 */
     8class BP_Tests_BP_Single_Item_Navigation extends BP_UnitTestCase {
     9        public function setUp() {
     10                parent::setUp();
     11                $this->current_user = get_current_user_id();
     12        }
     13
     14        public function tearDown() {
     15                $this->set_current_user( $this->current_user );
     16                parent::tearDown();
     17        }
     18        /**
     19         * @group blogs_item_nav
     20         */
     21        public function test_class_for_blogs_single_item() {
     22                if ( ! is_multisite() ) {
     23                        $this->markTestSkipped( __METHOD__ . ' is a multisite-only test.' );
     24                }
     25
     26                $bp = buddypress();
     27
     28                $reset_is_single_item = $bp->is_single_item;
     29                $reset_current_item   = $bp->current_item;
     30                $reset_current_action = $bp->current_action;
     31
     32                $a = $this->factory->user->create();
     33                $b = $this->factory->blog->create( array( 'user_id' => $a ) );
     34
     35                $u = $this->factory->user->create();
     36
     37                $bp->blogs->current_blog = get_blog_details( $b );
     38                $bp->blogs->current_blog->slug = trim( str_replace( get_current_site()->path, '', $bp->blogs->current_blog->path ), '/' );
     39                $bp->blogs->current_blog->item_id = $b;
     40
     41                // It's a blog single item
     42                $bp->is_single_item  = true;
     43                $bp->current_item    = $bp->blogs->current_blog->slug;
     44
     45                // Public blogs
     46                $bp->blogs->current_blog->user_has_access = true;
     47
     48                // Admin is loggedin
     49                $this->set_current_user( $a );
     50                bp_update_is_item_admin( true, $bp->blogs->id );
     51
     52                // Init the single nav
     53                $bp->blogs->nav = new BP_Single_Item_Navigation( array(
     54                        'component_id'       => $bp->blogs->id,
     55                        'component_slug'     => bp_get_blogs_root_slug(),
     56                        'single_item_name'   => 'blog',
     57                        'single_item_object' => $bp->blogs->current_blog,
     58                ) );
     59
     60                $blog_link = trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() . '/'. $bp->blogs->current_blog->slug );
     61
     62                $item_main_nav = array(
     63                        trailingslashit( $blog_link . 'home' ) => array(
     64                                'name'                => __( 'Home', 'buddypress' ),
     65                                'slug'                => 'home',
     66                                'position'            => 0,
     67                                'screen_function'     => 'screen_blog_home',
     68                                'default_subnav_slug' => false,
     69                        ),
     70                        trailingslashit( $blog_link . 'manage' ) => array(
     71                                'name'                => __( 'Manage', 'buddypress' ),
     72                                'slug'                => 'manage',
     73                                'position'            => 1000,
     74                                'screen_function'     => 'screen_blog_settings',
     75                                'default_subnav_slug' => 'manage',
     76                                'item_admin_only'     => true,
     77                        ),
     78                );
     79
     80                $item_sub_nav = array(
     81                        trailingslashit( $blog_link . 'manage' ) => array(
     82                                'name'              => __( 'Settings','buddypress' ),
     83                                'slug'              => 'manage',
     84                                'parent_slug'       => 'manage',
     85                                'screen_function'   => 'screen_blog_settings',
     86                                'position'          => 0,
     87                                'item_admin_only'   => true,
     88                        ),
     89                );
     90
     91                // Setup the nav for the admin
     92                $bp->blogs->nav->setup_nav( $item_main_nav, $item_sub_nav );
     93
     94                $tested = array();
     95
     96                // Catch the main nav
     97                ob_start();
     98                $bp->blogs->nav->display_main_nav();
     99                $tested['main'] = ob_get_contents();
     100                ob_end_clean();
     101
     102                // Set the manage action
     103                $bp->current_action = 'manage';
     104
     105                // Catch the sub nav
     106                ob_start();
     107                $bp->blogs->nav->display_sub_nav();
     108                $tested['sub'] = ob_get_contents();
     109                ob_end_clean();
     110
     111                // Test main nav links
     112                preg_match_all( '#href=(["\'])([^"\']+)\1#i', $tested['main'], $main_matches );
     113                $this->assertSame( array_keys( $item_main_nav ), $main_matches[2] );
     114
     115                // Test sub nav links
     116                preg_match_all( '#href=(["\'])([^"\']+)\1#i', $tested['sub'], $sub_matches );
     117                $this->assertSame( array_keys( $item_sub_nav ), $sub_matches[2] );
     118
     119                // Test if reseting the nav is ok
     120                foreach ( $item_main_nav as $item ) {
     121                        $bp->blogs->nav->remove_main_nav_item( $bp->blogs->id, $b, $item['slug'] );
     122                }
     123
     124                $this->assertEmpty( $bp->blogs->nav->main[ $b ] );
     125
     126                $tested = array();
     127
     128                // a random user is loggedin
     129                $this->set_current_user( $u );
     130                bp_update_is_item_admin( false, $bp->blogs->id );
     131
     132                // Set the home action
     133                $bp->current_action = 'home';
     134
     135                // Setup the nav for the user
     136                $bp->blogs->nav->setup_nav( $item_main_nav, $item_sub_nav );
     137
     138                // Catch the main nav
     139                ob_start();
     140                $bp->blogs->nav->display_main_nav();
     141                $tested['main'] = ob_get_contents();
     142                ob_end_clean();
     143
     144                // Set the manage action
     145                $bp->current_action = 'manage';
     146
     147                // Catch the sub nav
     148                ob_start();
     149                $bp->blogs->nav->display_sub_nav();
     150                $tested['sub'] = ob_get_contents();
     151                ob_end_clean();
     152
     153                // Test main nav links
     154                preg_match_all( '#href=(["\'])([^"\']+)\1#i', $tested['main'], $main_matches );
     155                $this->assertSame( array( trailingslashit( $blog_link . 'home' ) ), $main_matches[2] );
     156
     157                // Sub nav should be empty
     158                $this->assertEmpty( $tested['sub'] );
     159
     160                // Reset the blogs component
     161                unset( $bp->blogs->nav );
     162                unset( $bp->blogs->current_blog );
     163
     164                // Reset globals
     165                $bp->is_single_item = $reset_is_single_item;
     166                $bp->current_item   = $reset_current_item;
     167                $bp->current_action = $reset_current_action;
     168        }
     169}