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


Generated: Fri Jul 30 01:01:42 2021 Cross-referenced by PHPXref 0.7.1