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