[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-core/ -> bp-core-buddybar.php (source)

   1  <?php
   2  /**
   3   * Core BuddyPress Navigational Functions.
   4   *
   5   * @package BuddyPress
   6   * @subpackage Core
   7   * @since 1.5.0
   8   *
   9   * @todo Deprecate BuddyBar functions.
  10   */
  11  
  12  // Exit if accessed directly.
  13  defined( 'ABSPATH' ) || exit;
  14  
  15  /**
  16   * Add an item to the primary navigation of the specified component.
  17   *
  18   * @since 1.1.0
  19   * @since 2.6.0 Introduced the `$component` parameter.
  20   * @since 4.0.0 Introduced the `$component_id` argument.
  21   *
  22   * @param array|string $args {
  23   *     Array describing the new nav item.
  24   *     @type string      $name                    Display name for the nav item.
  25   *     @type string      $slug                    Unique URL slug for the nav item.
  26   *     @type string      $component_id            Optional. The ID of the component registering the nav item. Defaults to slug.
  27   *     @type bool|string $item_css_id             Optional. 'id' attribute for the nav item. Default: the value of `$slug`.
  28   *     @type bool        $show_for_displayed_user Optional. Whether the nav item should be visible when viewing a
  29   *                                                member profile other than your own. Default: true.
  30   *     @type bool        $site_admin_only         Optional. Whether the nav item should be visible only to site admins
  31   *                                                (those with the 'bp_moderate' cap). Default: false.
  32   *     @type int         $position                Optional. Numerical index specifying where the item should appear in
  33   *                                                the nav array. Default: 99.
  34   *     @type callable    $screen_function         The callback function that will run when the nav item is clicked.
  35   *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
  36   *                                                item is clicked.
  37   * }
  38   * @param string       $component The component the navigation is attached to. Defaults to 'members'.
  39   * @return null|false Returns false on failure.
  40   */
  41  function bp_core_new_nav_item( $args, $component = 'members' ) {
  42      if ( ! bp_is_active( $component ) ) {
  43          return;
  44      }
  45  
  46      $defaults = array(
  47          'name'                    => false, // Display name for the nav item.
  48          'slug'                    => false, // URL slug for the nav item.
  49          'component_id'            => '',    // ID of the component registering the nav item.
  50          'item_css_id'             => false, // The CSS ID to apply to the HTML of the nav item.
  51          'show_for_displayed_user' => true,  // When viewing another user does this nav item show up?
  52          'site_admin_only'         => false, // Can only site admins see this nav item?
  53          'position'                => 99,    // Index of where this nav item should be positioned.
  54          'screen_function'         => false, // The name of the function to run when clicked.
  55          'default_subnav_slug'     => false  // The slug of the default subnav item to select when clicked.
  56      );
  57  
  58      $r = wp_parse_args( $args, $defaults );
  59  
  60      // Validate nav link data.
  61      $nav_item = bp_core_create_nav_link( $r, $component );
  62  
  63      /*
  64       * To mimic legacy behavior, if bp_core_create_nav_link() returns false, we make
  65       * an early exit and don't attempt to register the screen function.
  66       */
  67      if ( false === $nav_item ) {
  68          return false;
  69      }
  70  
  71      // Then, hook the screen function for the added nav item.
  72      $hooked = bp_core_register_nav_screen_function( $nav_item );
  73      if ( false === $hooked ){
  74          return false;
  75      }
  76  
  77      /**
  78       * Fires after adding an item to the main BuddyPress navigation array.
  79       * Note that, when possible, the more specific action hooks
  80       * `bp_core_create_nav_link` or `bp_core_register_nav_screen_function`
  81       * should be used.
  82       *
  83       * @since 1.5.0
  84       *
  85       * @param array $r        Parsed arguments for the nav item.
  86       * @param array $args     Originally passed in arguments for the nav item.
  87       * @param array $defaults Default arguments for a nav item.
  88       */
  89      do_action( 'bp_core_new_nav_item', $r, $args, $defaults );
  90  }
  91  
  92  /**
  93   * Add a link to the main BuddyPress navigation.
  94   *
  95   * @since 2.4.0
  96   * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Core_Nav_Item
  97   *              object on success.
  98   * @since 4.0.0 Introduced `$component_id` argument.
  99   *
 100   * @param array|string $args {
 101   *     Array describing the new nav item.
 102   *     @type string      $component_id            Optional. The ID of the component registering this nav item. Defaults to the
 103   *                                                the value of `$slug`.
 104   *     @type string      $name                    Display name for the nav item.
 105   *     @type string      $slug                    Unique URL slug for the nav item.
 106   *     @type bool|string $item_css_id             Optional. 'id' attribute for the nav item. Default: the value of `$slug`.
 107   *     @type bool        $show_for_displayed_user Optional. Whether the nav item should be visible when viewing a
 108   *                                                member profile other than your own. Default: true.
 109   *     @type bool        $site_admin_only         Optional. Whether the nav item should be visible only to site admins
 110   *                                                (those with the 'bp_moderate' cap). Default: false.
 111   *     @type int         $position                Optional. Numerical index specifying where the item should appear in
 112   *                                                the nav array. Default: 99.
 113   *     @type callable    $screen_function         The callback function that will run when the nav item is clicked.
 114   *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
 115   *                                                item is clicked.
 116   * }
 117   * @param string       $component Optional. Component that the nav belongs to.
 118   * @return false|array Returns false on failure, new nav item on success.
 119   */
 120  function bp_core_create_nav_link( $args = '', $component = 'members' ) {
 121      $bp = buddypress();
 122  
 123      $defaults = array(
 124          'component_id'            => '',    // The component ID registering this nav item.
 125          'name'                    => false, // Display name for the nav item.
 126          'slug'                    => false, // URL slug for the nav item.
 127          'item_css_id'             => false, // The CSS ID to apply to the HTML of the nav item.
 128          'show_for_displayed_user' => true,  // When viewing another user does this nav item show up?
 129          'site_admin_only'         => false, // Can only site admins see this nav item?
 130          'position'                => 99,    // Index of where this nav item should be positioned.
 131          'screen_function'         => false, // The name of the function to run when clicked.
 132          'default_subnav_slug'     => false  // The slug of the default subnav item to select when clicked.
 133      );
 134  
 135      $r = wp_parse_args( $args, $defaults );
 136  
 137      // If we don't have the required info we need, don't create this nav item.
 138      if ( empty( $r['name'] ) || empty( $r['slug'] ) ) {
 139          return false;
 140      }
 141  
 142      // If this is for site admins only and the user is not one, don't create the nav item.
 143      if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
 144          return false;
 145      }
 146  
 147      if ( empty( $r['component_id'] ) ) {
 148          $r['component_id'] = $r['slug'];
 149      }
 150  
 151      if ( empty( $r['item_css_id'] ) ) {
 152          $r['item_css_id'] = $r['slug'];
 153      }
 154  
 155      $nav_item = array(
 156          'component_id'            => $r['component_id'],
 157          'name'                    => $r['name'],
 158          'slug'                    => $r['slug'],
 159          'link'                    => trailingslashit( bp_loggedin_user_domain() . $r['slug'] ),
 160          'css_id'                  => $r['item_css_id'],
 161          'show_for_displayed_user' => $r['show_for_displayed_user'],
 162          'position'                => $r['position'],
 163          'screen_function'         => &$r['screen_function'],
 164          'default_subnav_slug'      => $r['default_subnav_slug']
 165      );
 166  
 167      // Add the item to the nav.
 168      buddypress()->{$component}->nav->add_nav( $nav_item );
 169  
 170      /**
 171       * Fires after a link is added to the main BuddyPress nav.
 172       *
 173       * @since 2.4.0
 174       * @since 2.6.0 Added `$component` parameter.
 175       *
 176       * @param array  $r         Parsed arguments for the nav item.
 177       * @param array  $args      Originally passed in arguments for the nav item.
 178       * @param array  $defaults  Default arguments for a nav item.
 179       * @param string $component Component that the nav belongs to.
 180       */
 181      do_action( 'bp_core_create_nav_link', $r, $args, $defaults, $component );
 182  
 183      return $nav_item;
 184  }
 185  
 186  /**
 187   * Register a screen function for an item in the main nav array.
 188   *
 189   * @since 2.4.0
 190   *
 191   * @param array|string $args {
 192   *     Array describing the new nav item.
 193   *     @type string      $name                    Display name for the nav item.
 194   *     @type string      $slug                    Unique URL slug for the nav item.
 195   *     @type bool|string $item_css_id             Optional. 'id' attribute for the nav item. Default: the value of `$slug`.
 196   *     @type bool        $show_for_displayed_user Optional. Whether the nav item should be visible when viewing a
 197   *                                                member profile other than your own. Default: true.
 198   *     @type bool        $site_admin_only         Optional. Whether the nav item should be visible only to site admins
 199   *                                                (those with the 'bp_moderate' cap). Default: false.
 200   *     @type int         $position                Optional. Numerical index specifying where the item should appear in
 201   *                                                the nav array. Default: 99.
 202   *     @type callable    $screen_function         The callback function that will run when the nav item is clicked.
 203   *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
 204   *                                                item is clicked.
 205   * }
 206   * @return false|null Returns false on failure.
 207   */
 208  function bp_core_register_nav_screen_function( $args = '' ) {
 209      $bp = buddypress();
 210  
 211      $defaults = array(
 212          'name'                    => false, // Display name for the nav item.
 213          'slug'                    => false, // URL slug for the nav item.
 214          'item_css_id'             => false, // The CSS ID to apply to the HTML of the nav item.
 215          'show_for_displayed_user' => true,  // When viewing another user does this nav item show up?
 216          'site_admin_only'         => false, // Can only site admins see this nav item?
 217          'position'                => 99,    // Index of where this nav item should be positioned.
 218          'screen_function'         => false, // The name of the function to run when clicked.
 219          'default_subnav_slug'     => false  // The slug of the default subnav item to select when clicked.
 220      );
 221  
 222      $r = wp_parse_args( $args, $defaults );
 223  
 224      // If we don't have the required info we need, don't register this screen function.
 225      if ( empty( $r['slug'] ) ) {
 226          return false;
 227      }
 228  
 229      /**
 230       * If this is for site admins only and the user is not one,
 231       * don't register this screen function.
 232       */
 233      if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
 234          return false;
 235      }
 236  
 237      /**
 238       * If this nav item is hidden for the displayed user, and
 239       * the logged in user is not the displayed user
 240       * looking at their own profile, don't don't register this screen function.
 241       */
 242      if ( empty( $r['show_for_displayed_user'] ) && ! bp_user_has_access() ) {
 243          return false;
 244      }
 245  
 246      /**
 247       * If the nav item is visible, we are not viewing a user, and this is a root
 248       * component, don't attach the default subnav function so we can display a
 249       * directory or something else.
 250       */
 251      if ( ( -1 != $r['position'] ) && bp_is_root_component( $r['slug'] ) && ! bp_displayed_user_id() ) {
 252          return;
 253      }
 254  
 255      // Look for current component.
 256      if ( bp_is_current_component( $r['slug'] ) || bp_is_current_item( $r['slug'] ) ) {
 257  
 258          // The requested URL has explicitly included the default subnav
 259          // (eg: http://example.com/members/membername/activity/just-me/)
 260          // The canonical version will not contain this subnav slug.
 261          if ( ! empty( $r['default_subnav_slug'] ) && bp_is_current_action( $r['default_subnav_slug'] ) && ! bp_action_variable( 0 ) ) {
 262              unset( $bp->canonical_stack['action'] );
 263          } elseif ( ! bp_current_action() ) {
 264  
 265              // Add our screen hook if screen function is callable.
 266              if ( is_callable( $r['screen_function'] ) ) {
 267                  add_action( 'bp_screens', $r['screen_function'], 3 );
 268              }
 269  
 270              if ( ! empty( $r['default_subnav_slug'] ) ) {
 271  
 272                  /**
 273                   * Filters the default component subnav item.
 274                   *
 275                   * @since 1.5.0
 276                   *
 277                   * @param string $value The slug of the default subnav item
 278                   *                      to select when clicked.
 279                   * @param array  $r     Parsed arguments for the nav item.
 280                   */
 281                  $bp->current_action = apply_filters( 'bp_default_component_subnav', $r['default_subnav_slug'], $r );
 282              }
 283          }
 284      }
 285  
 286      /**
 287       * Fires after the screen function for an item in the BuddyPress main
 288       * navigation is registered.
 289       *
 290       * @since 2.4.0
 291       *
 292       * @param array $r        Parsed arguments for the nav item.
 293       * @param array $args     Originally passed in arguments for the nav item.
 294       * @param array $defaults Default arguments for a nav item.
 295       */
 296      do_action( 'bp_core_register_nav_screen_function', $r, $args, $defaults );
 297  }
 298  
 299  /**
 300   * Modify the default subnav item that loads when a top level nav item is clicked.
 301   *
 302   * @since 1.1.0
 303   *
 304   * @param array|string $args {
 305   *     @type string   $parent_slug     The slug of the nav item whose default is being changed.
 306   *     @type callable $screen_function The new default callback function that will run when the nav item is clicked.
 307   *     @type string   $subnav_slug     The slug of the new default subnav item.
 308   * }
 309   */
 310  function bp_core_new_nav_default( $args = '' ) {
 311      $bp = buddypress();
 312  
 313      $defaults = array(
 314          'parent_slug'     => false, // Slug of the parent.
 315          'screen_function' => false, // The name of the function to run when clicked.
 316          'subnav_slug'     => false  // The slug of the subnav item to select when clicked.
 317      );
 318  
 319      $r = wp_parse_args( $args, $defaults );
 320  
 321      // This is specific to Members - it's not available in Groups.
 322      $parent_nav = $bp->members->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
 323  
 324      if ( ! $parent_nav ) {
 325          return ;
 326      }
 327  
 328      $parent_nav = reset( $parent_nav );
 329  
 330      if ( ! empty( $parent_nav->screen_function ) ) {
 331          // Remove our screen hook if screen function is callable.
 332          if ( is_callable( $parent_nav->screen_function ) ) {
 333              remove_action( 'bp_screens', $parent_nav->screen_function, 3 );
 334          }
 335      }
 336  
 337      // Edit the screen function for the parent nav.
 338      $bp->members->nav->edit_nav( array(
 339          'screen_function'     => &$r['screen_function'],
 340          'default_subnav_slug' => $r['subnav_slug'],
 341      ), $parent_nav->slug );
 342  
 343      if ( bp_is_current_component( $parent_nav->slug ) ) {
 344  
 345          // The only way to tell whether to set the subnav is to peek at the unfiltered_uri
 346          // Find the component.
 347          $component_uri_key = array_search( $parent_nav->slug, $bp->unfiltered_uri );
 348  
 349          if ( false !== $component_uri_key ) {
 350              if ( ! empty( $bp->unfiltered_uri[$component_uri_key + 1] ) ) {
 351                  $unfiltered_action = $bp->unfiltered_uri[$component_uri_key + 1];
 352              }
 353          }
 354  
 355          // No subnav item has been requested in the URL, so set a new nav default.
 356          if ( empty( $unfiltered_action ) ) {
 357              if ( ! bp_is_current_action( $r['subnav_slug'] ) ) {
 358                  /*
 359                   * If the screen function isn't available, attempt to find it.
 360                   *
 361                   * This is due to our conditional-loading code since v3.0.0.
 362                   */
 363                  if ( ! is_callable( $r['screen_function'] ) && ! empty( $parent_nav->component_id ) ) {
 364                      $file      = $bp->core->path . 'bp-' . $parent_nav->component_id . '/screens/' . $r['subnav_slug'] . '.php';
 365                      $file_path = realpath( $file );
 366  
 367                      // Found the file, so require it.
 368                      if ( $file === $file_path && file_exists( $file ) ) {
 369                          require_once $file;
 370                      }
 371                  }
 372  
 373                  if ( is_callable( $r['screen_function'] ) ) {
 374                      add_action( 'bp_screens', $r['screen_function'], 3 );
 375                  }
 376  
 377                  $bp->current_action = $r['subnav_slug'];
 378                  unset( $bp->canonical_stack['action'] );
 379              }
 380  
 381          // The URL is explicitly requesting the new subnav item, but should be
 382          // directed to the canonical URL.
 383          } elseif ( $unfiltered_action == $r['subnav_slug'] ) {
 384              unset( $bp->canonical_stack['action'] );
 385  
 386          // In all other cases (including the case where the original subnav item
 387          // is explicitly called in the URL), the canonical URL will contain the
 388          // subnav slug.
 389          } else {
 390              $bp->canonical_stack['action'] = bp_current_action();
 391          }
 392      }
 393  
 394      return;
 395  }
 396  
 397  /**
 398   * Add an item to secondary navigation of the specified component.
 399   *
 400   * @since 1.1.0
 401   * @since 2.6.0 Introduced the `$component` parameter.
 402   *
 403   * @param array|string $args {
 404   *     Array describing the new subnav item.
 405   *     @type string      $name              Display name for the subnav item.
 406   *     @type string      $slug              Unique URL slug for the subnav item.
 407   *     @type string      $parent_slug       Slug of the top-level nav item under which the new subnav item should
 408   *                                          be added.
 409   *     @type string      $parent_url        URL of the parent nav item.
 410   *     @type bool|string $item_css_id       Optional. 'id' attribute for the nav item. Default: the value of `$slug`.
 411   *     @type bool        $user_has_access   Optional. True if the logged-in user has access to the subnav item,
 412   *                                          otherwise false. Can be set dynamically when registering the subnav;
 413   *                                          eg, use `bp_is_my_profile()` to restrict access to profile owners only.
 414   *                                          Default: true.
 415   *     @type bool        $site_admin_only   Optional. Whether the nav item should be visible only to site admins
 416   *                                          (those with the 'bp_moderate' cap). Default: false.
 417   *     @type int         $position          Optional. Numerical index specifying where the item should appear in the
 418   *                                          subnav array. Default: 90.
 419   *     @type callable    $screen_function   The callback function that will run when the nav item is clicked.
 420   *     @type string      $link              Optional. The URL that the subnav item should point to. Defaults to a value
 421   *                                          generated from the `$parent_url` + `$slug`.
 422   *     @type bool        $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit"
 423   *                                          Admin Bar menu for group admins. Default: false.
 424   * }
 425   * @param string|null    $component The component the navigation is attached to. Defaults to 'members'.
 426   * @return null|false Returns false on failure.
 427   */
 428  function bp_core_new_subnav_item( $args, $component = null ) {
 429      // Backward compatibility for plugins using `bp_core_new_subnav_item()` without `$component`
 430      // to add group subnav items.
 431      if ( null === $component && bp_is_active( 'groups' ) && bp_is_group() && isset( $args['parent_slug'] ) ) {
 432          /*
 433           * Assume that this item is intended to belong to the current group if:
 434           * a) the 'parent_slug' is the same as the slug of the current group, or
 435           * b) the 'parent_slug' starts with the slug of the current group, and the members nav doesn't have
 436           *    a primary item with that slug.
 437           */
 438          $group_slug = bp_get_current_group_slug();
 439          if (
 440              $group_slug === $args['parent_slug'] ||
 441              ( 0 === strpos( $args['parent_slug'], $group_slug ) && ! buddypress()->members->nav->get_primary( array( 'slug' => $args['parent_slug'] ), false ) )
 442          ) {
 443              $component = 'groups';
 444          }
 445      }
 446  
 447      if ( ! $component ) {
 448          $component = 'members';
 449      }
 450  
 451      if ( ! bp_is_active( $component ) ) {
 452          return;
 453      }
 454  
 455      // First, register the subnav item in the nav.
 456      $subnav_item = bp_core_create_subnav_link( $args, $component );
 457  
 458      /*
 459       * To mimic legacy behavior, if bp_core_create_subnav_link() returns false, we make an
 460       * early exit and don't attempt to register the screen function.
 461       */
 462      if ( false === $subnav_item ) {
 463          return false;
 464      }
 465  
 466      // Then, hook the screen function for the added subnav item.
 467      $hooked = bp_core_register_subnav_screen_function( $subnav_item, $component );
 468      if ( false === $hooked ) {
 469          return false;
 470      }
 471  }
 472  
 473  /**
 474   * Add a subnav link to the BuddyPress navigation.
 475   *
 476   * @since 2.4.0
 477   * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Core_Nav_Item object on success.
 478   *
 479   * @param array|string $args {
 480   *     Array describing the new subnav item.
 481   *     @type string      $name              Display name for the subnav item.
 482   *     @type string      $slug              Unique URL slug for the subnav item.
 483   *     @type string      $parent_slug       Slug of the top-level nav item under which the
 484   *                                          new subnav item should be added.
 485   *     @type string      $parent_url        URL of the parent nav item.
 486   *     @type bool|string $item_css_id       Optional. 'id' attribute for the nav
 487   *                                          item. Default: the value of $slug.
 488   *     @type bool        $user_has_access   Optional. True if the logged-in user has access to the
 489   *                                          subnav item, otherwise false. Can be set dynamically
 490   *                                          when registering the subnav; eg, use bp_is_my_profile()
 491   *                                          to restrict access to profile owners only. Default: true.
 492   *     @type bool        $site_admin_only   Optional. Whether the nav item should be visible only
 493   *                                          to site admins (those with the 'bp_moderate' cap).
 494   *                                          Default: false.
 495   *     @type int         $position          Optional. Numerical index specifying where the item
 496   *                                          should appear in the subnav array. Default: 90.
 497   *     @type callable    $screen_function   The callback function that will run
 498   *                                          when the nav item is clicked.
 499   *     @type string      $link              Optional. The URL that the subnav item should point
 500   *                                          to. Defaults to a value generated from the $parent_url + $slug.
 501   *     @type bool        $show_in_admin_bar Optional. Whether the nav item should be added into
 502   *                                          the group's "Edit" Admin Bar menu for group admins.
 503   *                                          Default: false.
 504   * }
 505   * @param string       $component The component the navigation is attached to. Defaults to 'members'.
 506   * @return false|array Returns false on failure, new BP_Core_Nav_Item instance on success.
 507   */
 508  function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
 509      $bp = buddypress();
 510  
 511      $r = wp_parse_args( $args, array(
 512          'name'              => false, // Display name for the nav item.
 513          'slug'              => false, // URL slug for the nav item.
 514          'parent_slug'       => false, // URL slug of the parent nav item.
 515          'parent_url'        => false, // URL of the parent item.
 516          'item_css_id'       => false, // The CSS ID to apply to the HTML of the nav item.
 517          'user_has_access'   => true,  // Can the logged in user see this nav item?
 518          'no_access_url'     => '',
 519          'site_admin_only'   => false, // Can only site admins see this nav item?
 520          'position'          => 90,    // Index of where this nav item should be positioned.
 521          'screen_function'   => false, // The name of the function to run when clicked.
 522          'link'              => '',    // The link for the subnav item; optional, not usually required.
 523          'show_in_admin_bar' => false, // Show the Manage link in the current group's "Edit" Admin Bar menu.
 524      ) );
 525  
 526      // If we don't have the required info we need, don't create this subnav item.
 527      if ( empty( $r['name'] ) || empty( $r['slug'] ) || empty( $r['parent_slug'] ) || empty( $r['parent_url'] ) || empty( $r['screen_function'] ) )
 528          return false;
 529  
 530      // Link was not forced, so create one.
 531      if ( empty( $r['link'] ) ) {
 532          $r['link'] = trailingslashit( $r['parent_url'] . $r['slug'] );
 533  
 534          $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
 535  
 536          // If this sub item is the default for its parent, skip the slug.
 537          if ( $parent_nav ) {
 538              $parent_nav_item = reset( $parent_nav );
 539              if ( ! empty( $parent_nav_item->default_subnav_slug ) && $r['slug'] === $parent_nav_item->default_subnav_slug ) {
 540                  $r['link'] = trailingslashit( $r['parent_url'] );
 541              }
 542          }
 543      }
 544  
 545      // If this is for site admins only and the user is not one, don't create the subnav item.
 546      if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
 547          return false;
 548      }
 549  
 550      if ( empty( $r['item_css_id'] ) ) {
 551          $r['item_css_id'] = $r['slug'];
 552      }
 553  
 554      $subnav_item = array(
 555          'name'              => $r['name'],
 556          'link'              => $r['link'],
 557          'slug'              => $r['slug'],
 558          'parent_slug'       => $r['parent_slug'],
 559          'css_id'            => $r['item_css_id'],
 560          'position'          => $r['position'],
 561          'user_has_access'   => $r['user_has_access'],
 562          'no_access_url'     => $r['no_access_url'],
 563          'screen_function'   => &$r['screen_function'],
 564          'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
 565      );
 566  
 567      buddypress()->{$component}->nav->add_nav( $subnav_item );
 568  
 569      return $subnav_item;
 570  }
 571  
 572  /**
 573   * Register a screen function, whether or not a related subnav link exists.
 574   *
 575   * @since 2.4.0
 576   * @since 2.6.0 Introduced the `$component` parameter.
 577   *
 578   * @param array|string $args {
 579   *     Array describing the new subnav item.
 580   *     @type string   $slug              Unique URL slug for the subnav item.
 581   *     @type string   $parent_slug       Slug of the top-level nav item under which the
 582   *                                       new subnav item should be added.
 583   *     @type string   $parent_url        URL of the parent nav item.
 584   *     @type bool     $user_has_access   Optional. True if the logged-in user has access to the
 585   *                                       subnav item, otherwise false. Can be set dynamically
 586   *                                       when registering the subnav; eg, use bp_is_my_profile()
 587   *                                       to restrict access to profile owners only. Default: true.
 588   *     @type bool     $site_admin_only   Optional. Whether the nav item should be visible
 589   *                                       only to site admins (those with the 'bp_moderate' cap).
 590   *                                       Default: false.
 591   *     @type int      $position          Optional. Numerical index specifying where the item
 592   *                                       should appear in the subnav array. Default: 90.
 593   *     @type callable $screen_function   The callback function that will run
 594   *                                       when the nav item is clicked.
 595   *     @type string   $link              Optional. The URL that the subnav item should point to.
 596   *                                       Defaults to a value generated from the $parent_url + $slug.
 597   *     @type bool     $show_in_admin_bar Optional. Whether the nav item should be added into
 598   *                                       the group's "Edit" Admin Bar menu for group admins.
 599   *                                       Default: false.
 600   * }
 601   * @param string       $component The component the navigation is attached to. Defaults to 'members'.
 602   * @return null|false Returns false on failure.
 603   */
 604  function bp_core_register_subnav_screen_function( $args = '', $component = 'members' ) {
 605      $bp = buddypress();
 606  
 607      $r = wp_parse_args( $args, array(
 608          'slug'              => false, // URL slug for the screen.
 609          'parent_slug'       => false, // URL slug of the parent screen.
 610          'user_has_access'   => true,  // Can the user visit this screen?
 611          'no_access_url'     => '',
 612          'site_admin_only'   => false, // Can only site admins visit this screen?
 613          'screen_function'   => false, // The name of the function to run when clicked.
 614      ) );
 615  
 616      /*
 617       * Hook the screen function for the added subnav item. But this only needs to
 618       * be done if this subnav item is the current view, and the user has access to the
 619       * subnav item. We figure out whether we're currently viewing this subnav by
 620       * checking the following two conditions:
 621       *   (1) Either:
 622       *       (a) the parent slug matches the current_component, or
 623       *       (b) the parent slug matches the current_item
 624       *   (2) And either:
 625       *       (a) the current_action matches $slug, or
 626       *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
 627       *       and this subnav item is the default for the parent item (which we check by
 628       *       comparing this subnav item's screen function with the screen function of the
 629       *       parent nav item in the component's primary nav). This condition only arises
 630       *       when viewing a user, since groups should always have an action set.
 631       */
 632  
 633      // If we *don't* meet condition (1), return.
 634      if ( ! bp_is_current_component( $r['parent_slug'] ) && ! bp_is_current_item( $r['parent_slug'] ) ) {
 635          return;
 636      }
 637  
 638      $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
 639      if ( is_array( $parent_nav ) ) {
 640          $parent_nav = reset( $parent_nav );
 641      }
 642  
 643      // If we *do* meet condition (2), then the added subnav item is currently being requested.
 644      if ( ( bp_current_action() && bp_is_current_action( $r['slug'] ) ) || ( bp_is_user() && ! bp_current_action() && ! empty( $parent_nav->screen_function ) && $r['screen_function'] == $parent_nav->screen_function ) ) {
 645  
 646          // If this is for site admins only and the user is not one, don't create the subnav item.
 647          if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
 648              return false;
 649          }
 650  
 651          $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r, $component );
 652  
 653          // If redirect args have been returned, perform the redirect now.
 654          if ( ! empty( $hooked['status'] ) && 'failure' === $hooked['status'] && isset( $hooked['redirect_args'] ) ) {
 655              bp_core_no_access( $hooked['redirect_args'] );
 656          }
 657      }
 658  }
 659  
 660  /**
 661   * For a given subnav item, either hook the screen function or generate redirect arguments, as necessary.
 662   *
 663   * @since 2.1.0
 664   * @since 2.6.0 Introduced the `$component` parameter.
 665   *
 666   * @param array  $subnav_item The subnav array added to the secondary navigation of
 667   *                            the component in bp_core_new_subnav_item().
 668   * @param string $component   The component the navigation is attached to. Defaults to 'members'.
 669   * @return array
 670   */
 671  function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component = 'members' ) {
 672      $retval = array(
 673          'status' => '',
 674      );
 675  
 676      // Is this accessible by site admins only?
 677      $site_admin_restricted = false;
 678      if ( ! empty( $subnav_item['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
 679          $site_admin_restricted = true;
 680      }
 681  
 682      // User has access, so let's try to hook the display callback.
 683      if ( ! empty( $subnav_item['user_has_access'] ) && ! $site_admin_restricted ) {
 684  
 685          // Screen function is invalid.
 686          if ( ! is_callable( $subnav_item['screen_function'] ) ) {
 687              $retval['status'] = 'failure';
 688  
 689          // Success - hook to bp_screens.
 690          } else {
 691              add_action( 'bp_screens', $subnav_item['screen_function'], 3 );
 692              $retval['status'] = 'success';
 693          }
 694  
 695      // User doesn't have access. Determine redirect arguments based on
 696      // user status.
 697      } else {
 698          $retval['status'] = 'failure';
 699  
 700          if ( is_user_logged_in() ) {
 701  
 702              $bp = buddypress();
 703  
 704              // If a redirect URL has been passed to the subnav item, respect it.
 705              if ( ! empty( $subnav_item['no_access_url'] ) ) {
 706                  $message     = __( 'You do not have access to that page.', 'buddypress' );
 707                  $redirect_to = trailingslashit( $subnav_item['no_access_url'] );
 708  
 709              // In the case of a user page, we try to assume a
 710              // redirect URL.
 711              } elseif ( bp_is_user() ) {
 712  
 713                  $parent_nav_default = $bp->{$component}->nav->get_primary( array( 'slug' => $bp->default_component ), false );
 714                  if ( $parent_nav_default ) {
 715                      $parent_nav_default_item = reset( $parent_nav_default );
 716                  }
 717  
 718                  // Redirect to the displayed user's default
 719                  // component, as long as that component is
 720                  // publicly accessible.
 721                  if ( bp_is_my_profile() || ( isset( $parent_nav_default_item ) && $parent_nav_default_item->show_for_displayed_user ) ) {
 722                      $message     = __( 'You do not have access to that page.', 'buddypress' );
 723                      $redirect_to = bp_displayed_user_domain();
 724  
 725                  // In some cases, the default tab is not accessible to
 726                  // the logged-in user. So we fall back on a tab that we
 727                  // know will be accessible.
 728                  } else {
 729                      // Try 'activity' first.
 730                      if ( bp_is_active( 'activity' ) && isset( $bp->pages->activity ) ) {
 731                          $redirect_to = trailingslashit( bp_displayed_user_domain() . bp_get_activity_slug() );
 732                      // Then try 'profile'.
 733                      } else {
 734                          $redirect_to = trailingslashit( bp_displayed_user_domain() . ( 'xprofile' == $bp->profile->id ? 'profile' : $bp->profile->id ) );
 735                      }
 736  
 737                      $message     = '';
 738                  }
 739  
 740              // Fall back to the home page.
 741              } else {
 742                  $message     = __( 'You do not have access to this page.', 'buddypress' );
 743                  $redirect_to = bp_get_root_domain();
 744              }
 745  
 746              $retval['redirect_args'] = array(
 747                  'message'  => $message,
 748                  'root'     => $redirect_to,
 749                  'redirect' => false,
 750                  'mode'     => 1
 751              );
 752  
 753          } else {
 754              // When the user is logged out, pass an empty array
 755              // This indicates that the default arguments should be
 756              // used in bp_core_no_access().
 757              $retval['redirect_args'] = array();
 758          }
 759      }
 760  
 761      return $retval;
 762  }
 763  
 764  /**
 765   * Check whether a given nav item has subnav items.
 766   *
 767   * @since 1.5.0
 768   * @since 2.6.0 Introduced the `$component` parameter.
 769   *
 770   * @param string $nav_item  The slug of the top-level nav item whose subnav items you're checking.
 771   *                          Default: the current component slug.
 772   * @param string $component The component the navigation is attached to. Defaults to 'members'.
 773   * @return bool $has_subnav True if the nav item is found and has subnav items; false otherwise.
 774   */
 775  function bp_nav_item_has_subnav( $nav_item = '', $component = 'members' ) {
 776      $bp = buddypress();
 777  
 778      if ( ! isset( $bp->{$component}->nav ) ) {
 779          return false;
 780      }
 781  
 782      if ( ! $nav_item ) {
 783          $nav_item = bp_current_component();
 784  
 785          if ( bp_is_group() ) {
 786              $nav_item = bp_current_item();
 787          }
 788      }
 789  
 790      $has_subnav = (bool) $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $nav_item ), false );
 791  
 792      /**
 793       * Filters whether or not a given nav item has subnav items.
 794       *
 795       * @since 1.5.0
 796       *
 797       * @param bool   $has_subnav Whether or not there is any subnav items.
 798       * @param string $nav_item   The slug of the top-level nav item whose subnav items you're checking.
 799       */
 800      return apply_filters( 'bp_nav_item_has_subnav', $has_subnav, $nav_item );
 801  }
 802  
 803  /**
 804   * Deletes an item from the primary navigation of the specified component.
 805   *
 806   * @since 1.0.0
 807   * @since 2.6.0 Introduced the `$component` parameter.
 808   *
 809   * @param string      $slug      The slug of the primary navigation item.
 810   * @param string|null $component The component the navigation is attached to. Defaults to 'members'.
 811   * @return bool Returns false on failure, True on success.
 812   */
 813  function bp_core_remove_nav_item( $slug, $component = null ) {
 814      $bp = buddypress();
 815  
 816      // Backward compatibility for removing group nav items using the group slug as `$parent_slug`.
 817      if ( ! $component && bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
 818          if ( $bp->groups->nav->get_primary( array( 'slug' => $slug ) ) ) {
 819              $component = 'groups';
 820          }
 821      }
 822  
 823      if ( ! $component ) {
 824          $component = 'members';
 825      }
 826  
 827      if ( ! isset( $bp->{$component}->nav ) ) {
 828          return false;
 829      }
 830  
 831      $screen_functions = $bp->{$component}->nav->delete_nav( $slug );
 832  
 833      // Reset backcompat nav items so that subsequent references will be correct.
 834      $bp->bp_nav->reset();
 835      $bp->bp_options_nav->reset();
 836  
 837      if ( ! is_array( $screen_functions ) ) {
 838          return false;
 839      }
 840  
 841      foreach ( $screen_functions as $screen_function ) {
 842          // Remove our screen hook if screen function is callable.
 843          if ( is_callable( $screen_function ) ) {
 844              remove_action( 'bp_screens', $screen_function, 3 );
 845          }
 846      }
 847  
 848      return true;
 849  }
 850  
 851  /**
 852   * Deletes an item from the secondary navigation of the specified component.
 853   *
 854   * @since 1.0.0
 855   * @since 2.6.0 Introduced the `$component` parameter.
 856   *
 857   * @param string      $parent_slug The slug of the primary navigation item.
 858   * @param string      $slug        The slug of the secondary item to be removed.
 859   * @param string|null $component   The component the navigation is attached to. Defaults to 'members'.
 860   * @return bool Returns false on failure, True on success.
 861   */
 862  function bp_core_remove_subnav_item( $parent_slug, $slug, $component = null ) {
 863      $bp = buddypress();
 864  
 865      // Backward compatibility for removing group nav items using the group slug as `$parent_slug`.
 866      if ( ! $component && bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
 867          if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_slug ) ) ) {
 868              $component = 'groups';
 869          }
 870      }
 871  
 872      if ( ! $component ) {
 873          $component = 'members';
 874      }
 875  
 876      if ( ! isset( $bp->{$component}->nav ) ) {
 877          return false;
 878      }
 879  
 880      $screen_functions = $bp->{$component}->nav->delete_nav( $slug, $parent_slug );
 881  
 882      // Reset backcompat nav items so that subsequent references will be correct.
 883      $bp->bp_nav->reset();
 884      $bp->bp_options_nav->reset();
 885  
 886      if ( ! is_array( $screen_functions ) ) {
 887          return false;
 888      }
 889  
 890      $screen_function = reset( $screen_functions );
 891  
 892      // Remove our screen hook if screen function is callable.
 893      if ( is_callable( $screen_function ) ) {
 894          remove_action( 'bp_screens', $screen_function, 3 );
 895      }
 896  
 897      return true;
 898  }
 899  
 900  /**
 901   * Clear all subnav items from a specific nav item.
 902   *
 903   * @since 1.0.0
 904   * @since 2.6.0 Introduced the `$component` parameter.
 905   *
 906   * @param string $parent_slug The slug of the parent navigation item.
 907   * @param string $component   The component the navigation is attached to. Defaults to 'members'.
 908   */
 909  function bp_core_reset_subnav_items( $parent_slug, $component = 'members' ) {
 910      $bp = buddypress();
 911  
 912      if ( ! isset( $bp->{$component}->nav ) ) {
 913          return;
 914      }
 915  
 916      $subnav_items = $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $parent_slug ), false );
 917  
 918      if ( ! $subnav_items ) {
 919          return;
 920      }
 921  
 922      foreach( $subnav_items as $subnav_item ) {
 923          $bp->{$component}->nav->delete_nav( $subnav_item->slug, $parent_slug );
 924      }
 925  }
 926  
 927  
 928  /**
 929   * Retrieve the Toolbar display preference of a user based on context.
 930   *
 931   * This is a direct copy of WP's private _get_admin_bar_pref()
 932   *
 933   * @since 1.5.0
 934   *
 935   * @param string $context Context of this preference check. 'admin' or 'front'.
 936   * @param int    $user    Optional. ID of the user to check. Default: 0 (which falls back to the logged-in user's ID).
 937   * @return bool True if the toolbar should be showing for this user.
 938   */
 939  function bp_get_admin_bar_pref( $context, $user = 0 ) {
 940      $pref = get_user_option( "show_admin_bar_{$context}", $user );
 941      if ( false === $pref )
 942          return true;
 943  
 944      return 'true' === $pref;
 945  }


Generated: Tue Jul 16 01:01:43 2019 Cross-referenced by PHPXref 0.7.1