[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * BuddyPress Common Admin Functions. 4 * 5 * @package BuddyPress 6 * @subpackage CoreAdministration 7 * @since 2.3.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 /** Menu **********************************************************************/ 14 15 /** 16 * Initializes the wp-admin area "BuddyPress" menus and sub menus. 17 */ 18 function bp_core_admin_menu_init() { 19 add_action( bp_core_admin_hook(), 'bp_core_add_admin_menu', 9 ); 20 } 21 22 /** 23 * In BP 1.6, the top-level admin menu was removed. For backpat, this function 24 * keeps the top-level menu if a plugin has registered a menu into the old 25 * 'bp-general-settings' menu. 26 * 27 * The old "bp-general-settings" page was renamed "bp-components". 28 * 29 * @global array $_parent_pages 30 * @global array $_registered_pages 31 * @global array $submenu 32 * 33 * @since 1.6.0 34 */ 35 function bp_core_admin_backpat_menu() { 36 global $_parent_pages, $_registered_pages, $submenu; 37 38 // If there's no bp-general-settings menu (perhaps because the current 39 // user is not an Administrator), there's nothing to do here. 40 if ( ! isset( $submenu['bp-general-settings'] ) ) { 41 return; 42 } 43 44 /** 45 * By default, only the core "Help" submenu is added under the top-level BuddyPress menu. 46 * This means that if no third-party plugins have registered their admin pages into the 47 * 'bp-general-settings' menu, it will only contain one item. Kill it. 48 */ 49 if ( 1 != count( $submenu['bp-general-settings'] ) ) { 50 return; 51 } 52 53 // This removes the top-level menu. 54 remove_submenu_page( 'bp-general-settings', 'bp-general-settings' ); 55 remove_menu_page( 'bp-general-settings' ); 56 57 // These stop people accessing the URL directly. 58 unset( $_parent_pages['bp-general-settings'] ); 59 unset( $_registered_pages['toplevel_page_bp-general-settings'] ); 60 } 61 add_action( bp_core_admin_hook(), 'bp_core_admin_backpat_menu', 999 ); 62 63 /** 64 * This tells WP to highlight the Settings > BuddyPress menu item, 65 * regardless of which actual BuddyPress admin screen we are on. 66 * 67 * The conditional prevents the behavior when the user is viewing the 68 * backpat "Help" page, the Activity page, or any third-party plugins. 69 * 70 * @global string $plugin_page 71 * @global array $submenu 72 * 73 * @since 1.6.0 74 */ 75 function bp_core_modify_admin_menu_highlight() { 76 global $plugin_page, $submenu_file; 77 78 // This tweaks the Settings subnav menu to show only one BuddyPress menu item. 79 if ( ! in_array( $plugin_page, array( 'bp-activity', 'bp-general-settings' ) ) ) { 80 $submenu_file = 'bp-components'; 81 } 82 83 // Network Admin > Tools. 84 if ( in_array( $plugin_page, array( 'bp-tools', 'available-tools' ) ) ) { 85 $submenu_file = $plugin_page; 86 } 87 88 // Keep the BuddyPress tools menu highlighted when using a tools tab. 89 if ( 'bp-optouts' === $plugin_page || 'bp-members-invitations' === $plugin_page ) { 90 $submenu_file = 'bp-tools'; 91 } 92 } 93 94 /** 95 * Generates markup for a fallback top-level BuddyPress menu page, if the site is running 96 * a legacy plugin which hasn't been updated. If the site is up to date, this page 97 * will never appear. 98 * 99 * @see bp_core_admin_backpat_menu() 100 * 101 * @since 1.6.0 102 * 103 * @todo Add convenience links into the markup once new positions are finalized. 104 */ 105 function bp_core_admin_backpat_page() { 106 $url = bp_core_do_network_admin() ? network_admin_url( 'settings.php' ) : admin_url( 'options-general.php' ); 107 $settings_url = add_query_arg( 'page', 'bp-components', $url ); ?> 108 109 <div class="wrap"> 110 <h1 class="wp-heading-inline"><?php esc_html_e( 'Why have all my BuddyPress menus disappeared?', 'buddypress' ); ?></h1> 111 <hr class="wp-header-end"> 112 113 <p><?php esc_html_e( "Don't worry! We've moved the BuddyPress options into more convenient and easier to find locations. You're seeing this page because you are running a legacy BuddyPress plugin which has not been updated.", 'buddypress' ); ?></p> 114 <p> 115 <?php 116 printf( 117 // Translators: 1: is the url to the BP Components settings screen. 2: is the url to the xProfile administration screen. 118 __( 'Components, Pages, Settings, and Forums, have been moved to <a href="%1$s">Settings > BuddyPress</a>. Profile Fields has been moved into the <a href="%2$s">Users</a> menu.', 'buddypress' ), 119 esc_url( $settings_url ), 120 bp_get_admin_url( 'users.php?page=bp-profile-setup' ) 121 ); 122 ?> 123 </p> 124 </div> 125 126 <?php 127 } 128 129 /** Notices *******************************************************************/ 130 131 /** 132 * Print admin messages to admin_notices or network_admin_notices. 133 * 134 * BuddyPress combines all its messages into a single notice, to avoid a preponderance of yellow 135 * boxes. 136 * 137 * @since 1.5.0 138 */ 139 function bp_core_print_admin_notices() { 140 141 // Only the super admin should see messages. 142 if ( ! bp_current_user_can( 'bp_moderate' ) ) { 143 return; 144 } 145 146 // On multisite installs, don't show on a non-root blog, unless 147 // 'do_network_admin' is overridden. 148 if ( is_multisite() && bp_core_do_network_admin() && ! bp_is_root_blog() ) { 149 return; 150 } 151 152 $notice_types = array(); 153 foreach ( buddypress()->admin->notices as $notice ) { 154 $notice_types[] = $notice['type']; 155 } 156 $notice_types = array_unique( $notice_types ); 157 158 foreach ( $notice_types as $type ) { 159 $notices = wp_list_filter( buddypress()->admin->notices, array( 'type' => $type ) ); 160 printf( '<div id="message" class="fade %s notice is-dismissible">', sanitize_html_class( $type ) ); 161 162 foreach ( $notices as $notice ) { 163 printf( '<p>%s</p>', $notice['message'] ); 164 } 165 166 printf( '</div>' ); 167 } 168 } 169 add_action( 'admin_notices', 'bp_core_print_admin_notices' ); 170 add_action( 'network_admin_notices', 'bp_core_print_admin_notices' ); 171 172 /** 173 * Add an admin notice to the BP queue. 174 * 175 * Messages added with this function are displayed in BuddyPress's general purpose admin notices 176 * box. It is recommended that you hook this function to admin_init, so that your messages are 177 * loaded in time. 178 * 179 * @since 1.5.0 180 * 181 * @param string $notice The notice you are adding to the queue. 182 * @param string $type The notice type; optional. Usually either "updated" or "error". 183 */ 184 function bp_core_add_admin_notice( $notice = '', $type = 'updated' ) { 185 186 // Do not add if the notice is empty. 187 if ( empty( $notice ) ) { 188 return; 189 } 190 191 // Double check the object before referencing it. 192 if ( ! isset( buddypress()->admin->notices ) ) { 193 buddypress()->admin->notices = array(); 194 } 195 196 // Add the notice. 197 buddypress()->admin->notices[] = array( 198 'message' => $notice, 199 'type' => $type, 200 ); 201 } 202 203 /** 204 * Verify that some BP prerequisites are set up properly, and notify the admin if not. 205 * 206 * On every Dashboard page, this function checks the following: 207 * - that pretty permalinks are enabled. 208 * - that every BP component that needs a WP page for a directory has one. 209 * - that no WP page has multiple BP components associated with it. 210 * The administrator will be shown a notice for each check that fails. 211 * 212 * @global WPDB $wpdb WordPress DB object 213 * @global WP_Rewrite $wp_rewrite 214 * 215 * @since 1.2.0 216 */ 217 function bp_core_activation_notice() { 218 global $wp_rewrite, $wpdb; 219 220 // Only the super admin gets warnings. 221 if ( ! bp_current_user_can( 'bp_moderate' ) ) { 222 return; 223 } 224 225 // Bail in user admin. 226 if ( is_user_admin() ) { 227 return; 228 } 229 230 // On multisite installs, don't load on a non-root blog, unless do_network_admin is overridden. 231 if ( is_multisite() && bp_core_do_network_admin() && ! bp_is_root_blog() ) { 232 return; 233 } 234 235 // Bail if in network admin, and BuddyPress is not network activated. 236 if ( is_network_admin() && ! bp_is_network_activated() ) { 237 return; 238 } 239 240 /** 241 * Check to make sure that the blog setup routine has run. This can't 242 * happen during the wizard because of the order which the components 243 * are loaded. 244 */ 245 if ( bp_is_active( 'blogs' ) ) { 246 $bp = buddypress(); 247 $count = $wpdb->get_var( "SELECT COUNT(*) FROM {$bp->blogs->table_name}" ); 248 249 if ( empty( $count ) ) { 250 bp_blogs_record_existing_blogs(); 251 } 252 } 253 254 // Add notice if no rewrite rules are enabled. 255 if ( empty( $wp_rewrite->permalink_structure ) ) { 256 bp_core_add_admin_notice( 257 sprintf( 258 // Translators: %s is the url to the permalink settings. 259 __( '<strong>BuddyPress is almost ready</strong>. You must <a href="%s">update your permalink structure</a> to something other than the default for it to work.', 'buddypress' ), 260 admin_url( 'options-permalink.php' ) 261 ), 262 'error' 263 ); 264 } 265 266 // Get BuddyPress instance. 267 $bp = buddypress(); 268 269 /** 270 * Check for orphaned BP components (BP component is enabled, no WP page exists). 271 */ 272 $orphaned_components = array(); 273 $wp_page_components = array(); 274 275 // Only components with 'has_directory' require a WP page to function. 276 foreach ( array_keys( $bp->loaded_components ) as $component_id ) { 277 if ( ! empty( $bp->{$component_id}->has_directory ) ) { 278 $wp_page_components[] = array( 279 'id' => $component_id, 280 'name' => isset( $bp->{$component_id}->name ) ? $bp->{$component_id}->name : ucwords( $bp->{$component_id}->id ), 281 ); 282 } 283 } 284 285 // Activate and Register are special cases. They are not components but they need WP pages. 286 // If user registration is disabled, we can skip this step. 287 if ( bp_allow_access_to_registration_pages() ) { 288 $wp_page_components[] = array( 289 'id' => 'activate', 290 'name' => __( 'Activate', 'buddypress' ), 291 ); 292 293 $wp_page_components[] = array( 294 'id' => 'register', 295 'name' => __( 'Register', 'buddypress' ), 296 ); 297 } 298 299 // On the first admin screen after a new installation, this isn't set, so grab it to suppress 300 // a misleading error message. 301 if ( empty( $bp->pages->members ) ) { 302 $bp->pages = bp_core_get_directory_pages(); 303 } 304 305 foreach ( $wp_page_components as $component ) { 306 if ( ! isset( $bp->pages->{$component['id']} ) ) { 307 $orphaned_components[] = $component['name']; 308 } 309 } 310 311 if ( ! empty( $orphaned_components ) ) { 312 $admin_url = bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), 'admin.php' ) ); 313 $notice = sprintf( 314 '%1$s <a href="%2$s">%3$s</a>', 315 sprintf( 316 // Translators: %s is the comma separated list of components needing a directory page. 317 __( 'The following active BuddyPress Components do not have associated WordPress Pages: %s.', 'buddypress' ), 318 '<strong>' . implode( '</strong>, <strong>', array_map( 'esc_html', $orphaned_components ) ) . '</strong>' 319 ), 320 esc_url( $admin_url ), 321 __( 'Repair', 'buddypress' ) 322 ); 323 324 bp_core_add_admin_notice( $notice ); 325 } 326 327 // BP components cannot share a single WP page. Check for duplicate assignments, and post a message if found. 328 $dupe_names = array(); 329 $page_ids = bp_core_get_directory_page_ids(); 330 $dupes = array_diff_assoc( $page_ids, array_unique( $page_ids ) ); 331 332 if ( ! empty( $dupes ) ) { 333 foreach ( array_keys( $dupes ) as $dupe_component ) { 334 $dupe_names[] = $bp->pages->{$dupe_component}->title; 335 } 336 337 // Make sure that there are no duplicate duplicates :). 338 $dupe_names = array_unique( $dupe_names ); 339 } 340 341 // If there are duplicates, post a message about them. 342 if ( ! empty( $dupe_names ) ) { 343 $admin_url = bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), 'admin.php' ) ); 344 $notice = sprintf( 345 '%1$s <a href="%2$s">%3$s</a>', 346 sprintf( 347 // Translators: %s is the list of directory pages associated to more than one component. 348 __( 'Each BuddyPress Component needs its own WordPress page. The following WordPress Pages have more than one component associated with them: %s.', 'buddypress' ), 349 '<strong>' . implode( '</strong>, <strong>', array_map( 'esc_html', $dupe_names ) ) . '</strong>' 350 ), 351 esc_url( $admin_url ), 352 __( 'Repair', 'buddypress' ) 353 ); 354 355 bp_core_add_admin_notice( $notice ); 356 } 357 } 358 359 /** 360 * Redirect user to BuddyPress's What's New page on activation. 361 * 362 * @since 1.7.0 363 * 364 * @internal Used internally to redirect BuddyPress to the about page on activation. 365 */ 366 function bp_do_activation_redirect() { 367 368 // Bail if no activation redirect. 369 if ( ! get_transient( '_bp_activation_redirect' ) ) { 370 return; 371 } 372 373 // Delete the redirect transient. 374 delete_transient( '_bp_activation_redirect' ); 375 376 // Bail if activating from network, or bulk. 377 if ( isset( $_GET['activate-multi'] ) ) { 378 return; 379 } 380 381 $query_args = array(); 382 if ( get_transient( '_bp_is_new_install' ) ) { 383 $query_args['is_new_install'] = '1'; 384 delete_transient( '_bp_is_new_install' ); 385 } 386 387 // Redirect to dashboard and trigger the Hello screen. 388 wp_safe_redirect( add_query_arg( $query_args, bp_get_admin_url( '?hello=buddypress' ) ) ); 389 } 390 391 /** UI/Styling ****************************************************************/ 392 393 /** 394 * Outputs the BP Admin Tabbed header. 395 * 396 * @since 10.0.0 397 * 398 * @param string $title The title of the Admin page. 399 * @param string $active_tab The current displayed tab. 400 * @param string $context The context of use for the tabs. Defaults to 'settings'. 401 * Possible values are 'settings' & 'tools'. 402 */ 403 function bp_core_admin_tabbed_screen_header( $title = '', $active_tab = '', $context = 'settings' ) { 404 $bp = buddypress(); 405 406 // Globalize the active tab for backcompat purpose. 407 $bp->admin->active_nav_tab = $active_tab; 408 409 /** 410 * Fires before the output of the BP Admin tabbed screen header. 411 * 412 * @since 10.0.0 413 * 414 * @param string $active_tab The BP Admin active tab. 415 * @param string $context The context of use for the tabs. 416 */ 417 do_action( 'bp_core_admin_tabbed_screen_header', $active_tab, $context ); 418 ?> 419 <div class="buddypress-header"> 420 <div class="buddypress-title-section"> 421 <h1><span class="bp-badge"></span> <?php echo esc_html( $title ); ?></h1> 422 </div> 423 <nav class="buddypress-tabs-wrapper"> 424 <?php if ( isset( $bp->admin->nav_tabs ) ) : ?> 425 <?php foreach ( $bp->admin->nav_tabs as $nav_tab ) : ?> 426 427 <?php echo $nav_tab; ?> 428 429 <?php endforeach; ?> 430 <?php else : ?> 431 <?php bp_core_admin_tabs( esc_html( $active_tab ), $context ); ?> 432 <?php endif; ?> 433 </nav> 434 </div> 435 436 <hr class="wp-header-end"> 437 <?php 438 } 439 440 /** 441 * Output the tabs in the admin area. 442 * 443 * @since 1.5.0 444 * @since 8.0.0 Adds the `$context` parameter. 445 * 446 * @param string $active_tab Name of the tab that is active. Optional. 447 * @param string $context The context of use for the tabs. Defaults to 'settings'. 448 * Possible values are 'settings' & 'tools'. 449 */ 450 function bp_core_admin_tabs( $active_tab = '', $context = 'settings', $echo = true ) { 451 $tabs_html = ''; 452 $idle_class = 'buddypress-nav-tab'; 453 $active_class = 'buddypress-nav-tab active'; 454 455 /** 456 * Filters the admin tabs to be displayed. 457 * 458 * @since 1.9.0 459 * 460 * @param array $value Array of tabs to output to the admin area. 461 */ 462 $tabs = apply_filters( 'bp_core_admin_tabs', bp_core_get_admin_tabs( $active_tab, $context ) ); 463 $tabs_html = array(); 464 465 // Loop through tabs and build navigation. 466 foreach ( array_values( $tabs ) as $tab_data ) { 467 $is_current = (bool) ( $tab_data['name'] == $active_tab ); 468 $tab_class = $is_current ? $active_class : $idle_class; 469 $tabs_html[] = '<a href="' . esc_url( $tab_data['href'] ) . '" class="' . esc_attr( $tab_class ) . '">' . esc_html( $tab_data['name'] ) . '</a>'; 470 } 471 472 if ( ! $echo ) { 473 return $tabs_html; 474 } 475 476 echo implode( "\n", $tabs_html ); 477 /** 478 * Fires after the output of tabs for the admin area. 479 * 480 * @since 1.5.0 481 * @since 8.0.0 Adds the `$context` parameter. 482 * @since 10.0.0 Adds the `$active_tab` parameter. 483 * 484 * @param string $context The context of use for the tabs. 485 */ 486 do_action( 'bp_admin_tabs', $context, $active_tab ); 487 } 488 489 /** 490 * Returns the BP Admin settings tabs. 491 * 492 * @since 10.0.0 493 * 494 * @param bool $apply_filters Whether to apply filters or not. 495 * @return array The BP Admin settings tabs. 496 */ 497 function bp_core_get_admin_settings_tabs( $apply_filters = true ) { 498 $settings_tabs = array( 499 '0' => array( 500 'id' => 'bp-components', 501 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-components' ), 'admin.php' ) ), 502 'name' => __( 'Components', 'buddypress' ), 503 ), 504 '2' => array( 505 'id' => 'bp-settings', 506 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-settings' ), 'admin.php' ) ), 507 'name' => __( 'Options', 'buddypress' ), 508 ), 509 '1' => array( 510 'id' => 'bp-page-settings', 511 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-page-settings' ), 'admin.php' ) ), 512 'name' => __( 'Pages', 'buddypress' ), 513 ), 514 '3' => array( 515 'id' => 'bp-credits', 516 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-credits' ), 'admin.php' ) ), 517 'name' => __( 'Credits', 'buddypress' ), 518 ), 519 ); 520 521 if ( ! $apply_filters ) { 522 return $settings_tabs; 523 } 524 525 /** 526 * Filter here to edit the BP Admin settings tabs. 527 * 528 * @since 10.0.0 529 * 530 * @param array $settings_tabs The BP Admin settings tabs. 531 */ 532 return apply_filters( 'bp_core_get_admin_settings_tabs', $settings_tabs ); 533 } 534 535 /** 536 * Returns the BP Admin tools tabs. 537 * 538 * @since 10.0.0 539 * 540 * @param bool $apply_filters Whether to apply filters or not. 541 * @return array The BP Admin tools tabs. 542 */ 543 function bp_core_get_admin_tools_tabs( $apply_filters = true ) { 544 $tools_page = 'tools.php'; 545 if ( bp_core_do_network_admin() ) { 546 $tools_page = 'admin.php'; 547 } 548 549 $tools_tabs = array( 550 '0' => array( 551 'id' => 'bp-tools', 552 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-tools' ), $tools_page ) ), 553 'name' => __( 'Repair', 'buddypress' ), 554 ), 555 '1' => array( 556 'id' => 'bp-members-invitations', 557 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-members-invitations' ), $tools_page ) ), 558 'name' => __( 'Manage Invitations', 'buddypress' ), 559 ), 560 '2' => array( 561 'id' => 'bp-optouts', 562 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-optouts' ), $tools_page ) ), 563 'name' => __( 'Manage Opt-outs', 'buddypress' ), 564 ), 565 ); 566 567 if ( ! $apply_filters ) { 568 return $tools_tabs; 569 } 570 571 /** 572 * Filter here to edit the BP Admin tools tabs. 573 * 574 * @since 10.0.0 575 * 576 * @param array $tools_tabs The BP Admin tools tabs. 577 */ 578 return apply_filters( 'bp_core_get_admin_tools_tabs', $tools_tabs ); 579 } 580 581 /** 582 * Get the data for the tabs in the admin area. 583 * 584 * @since 2.2.0 585 * @since 8.0.0 Adds the `$context` parameter. 586 * 587 * @param string $active_tab Name of the tab that is active. Optional. 588 * @param string $context The context of use for the tabs. Defaults to 'settings'. 589 * Possible values are 'settings' & 'tools'. 590 * @return string 591 */ 592 function bp_core_get_admin_tabs( $active_tab = '', $context = 'settings' ) { 593 $tabs = array(); 594 595 if ( 'settings' === $context ) { 596 $tabs = bp_core_get_admin_settings_tabs(); 597 } elseif ( 'tools' === $context ) { 598 $tabs = bp_core_get_admin_tools_tabs(); 599 } 600 601 /** 602 * Filters the tab data used in our wp-admin screens. 603 * 604 * @since 2.2.0 605 * @since 8.0.0 Adds the `$context` parameter. 606 * 607 * @param array $tabs Tab data. 608 * @param string $context The context of use for the tabs. 609 */ 610 return apply_filters( 'bp_core_get_admin_tabs', $tabs, $context ); 611 } 612 613 /** 614 * Makes sure plugins using `bp_core_admin_tabs()` to output their custom BP Admin Tabs are well displayed 615 * inside the 10.0.0 tabbed header. 616 * 617 * @since 10.0.0 618 * 619 * @param string $context The context of use for the tabs. 620 * @param string $active_tab The active tab. 621 */ 622 function bp_backcompat_admin_tabs( $context = '', $active_tab = '' ) { 623 $bp = buddypress(); 624 625 // Only add the back compat for Settings or Tools sub pages. 626 if ( 'settings' !== $context && 'tools' !== $context ) { 627 return; 628 } 629 630 // Globalize the active tab for backcompat purpose. 631 if ( ! $bp->admin->active_nav_tab || $active_tab !== $bp->admin->active_nav_tab ) { 632 _doing_it_wrong( 633 'bp_core_admin_tabs()', 634 __( 'BuddyPress Settings and Tools Screens are now using a new tabbed header. Please use `bp_core_admin_tabbed_screen_header()` instead of bp_core_admin_tabs() to output tabs.', 'buddypress' ), 635 '10.0.0' 636 ); 637 638 // Let's try to use JavaScript to force the use of the 10.0.0 Admin tabbed screen header. 639 wp_enqueue_script( 640 'bp-backcompat-admin-tabs', 641 sprintf( '%1$sbackcompat-admin-tabs%2$s.js', $bp->admin->js_url, bp_core_get_minified_asset_suffix() ), 642 array(), 643 bp_get_version(), 644 true 645 ); 646 } 647 } 648 add_action( 'bp_admin_tabs', 'bp_backcompat_admin_tabs', 1, 2 ); 649 650 /** Help **********************************************************************/ 651 652 /** 653 * Adds contextual help to BuddyPress admin pages. 654 * 655 * @since 1.7.0 656 * @todo Make this part of the BP_Component class and split into each component. 657 * 658 * @param string $screen Current screen. 659 */ 660 function bp_core_add_contextual_help( $screen = '' ) { 661 662 $screen = get_current_screen(); 663 664 switch ( $screen->id ) { 665 666 // Component page. 667 case 'settings_page_bp-components': 668 // Help tabs. 669 $screen->add_help_tab( 670 array( 671 'id' => 'bp-comp-overview', 672 'title' => __( 'Overview', 'buddypress' ), 673 'content' => bp_core_add_contextual_help_content( 'bp-comp-overview' ), 674 ) 675 ); 676 677 // Help panel - sidebar links. 678 $screen->set_help_sidebar( 679 '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 680 '<p>' . __( '<a href="https://codex.buddypress.org/getting-started/configure-components/">Managing Components</a>', 'buddypress' ) . '</p>' . 681 '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 682 ); 683 break; 684 685 // Pages page. 686 case 'settings_page_bp-page-settings': 687 // Help tabs. 688 $screen->add_help_tab( 689 array( 690 'id' => 'bp-page-overview', 691 'title' => __( 'Overview', 'buddypress' ), 692 'content' => bp_core_add_contextual_help_content( 'bp-page-overview' ), 693 ) 694 ); 695 696 // Help panel - sidebar links. 697 $screen->set_help_sidebar( 698 '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 699 '<p>' . __( '<a href="https://codex.buddypress.org/getting-started/configure-components/#settings-buddypress-pages">Managing Pages</a>', 'buddypress' ) . '</p>' . 700 '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 701 ); 702 703 break; 704 705 // Settings page. 706 case 'settings_page_bp-settings': 707 // Help tabs. 708 $screen->add_help_tab( 709 array( 710 'id' => 'bp-settings-overview', 711 'title' => __( 'Overview', 'buddypress' ), 712 'content' => bp_core_add_contextual_help_content( 'bp-settings-overview' ), 713 ) 714 ); 715 716 // Help panel - sidebar links. 717 $screen->set_help_sidebar( 718 '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 719 '<p>' . __( '<a href="https://codex.buddypress.org/getting-started/configure-components/#settings-buddypress-settings">Managing Settings</a>', 'buddypress' ) . '</p>' . 720 '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 721 ); 722 723 break; 724 725 // Profile fields page. 726 case 'users_page_bp-profile-setup': 727 // Help tabs. 728 $screen->add_help_tab( 729 array( 730 'id' => 'bp-profile-overview', 731 'title' => __( 'Overview', 'buddypress' ), 732 'content' => bp_core_add_contextual_help_content( 'bp-profile-overview' ), 733 ) 734 ); 735 736 // Help panel - sidebar links. 737 $screen->set_help_sidebar( 738 '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 739 '<p>' . __( '<a href="https://codex.buddypress.org/administrator-guide/extended-profiles/">Managing Profile Fields</a>', 'buddypress' ) . '</p>' . 740 '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 741 ); 742 743 break; 744 } 745 } 746 add_action( 'load-settings_page_bp-components', 'bp_core_add_contextual_help' ); 747 add_action( 'load-settings_page_bp-page-settings', 'bp_core_add_contextual_help' ); 748 add_action( 'load-settings_page_bp-settings', 'bp_core_add_contextual_help' ); 749 add_action( 'load-users_page_bp-profile-setup', 'bp_core_add_contextual_help' ); 750 751 /** 752 * Renders contextual help content to contextual help tabs. 753 * 754 * @since 1.7.0 755 * 756 * @param string $tab Current help content tab. 757 * @return string 758 */ 759 function bp_core_add_contextual_help_content( $tab = '' ) { 760 761 switch ( $tab ) { 762 case 'bp-comp-overview': 763 $retval = __( 'By default, all but four of the BuddyPress components are enabled. You can selectively enable or disable any of the components by using the form below. Your BuddyPress installation will continue to function. However, the features of the disabled components will no longer be accessible to anyone using the site.', 'buddypress' ); 764 break; 765 766 case 'bp-page-overview': 767 $retval = __( 'BuddyPress Components use WordPress Pages for their root directory/archive pages. You can change the page associations for each active component by using the form below.', 'buddypress' ); 768 break; 769 770 case 'bp-settings-overview': 771 $retval = __( 'Extra configuration settings are provided and activated. You can selectively enable or disable any setting by using the form on this screen.', 'buddypress' ); 772 break; 773 774 case 'bp-profile-overview': 775 $retval = __( 'Your users will distinguish themselves through their profile page. Create relevant profile fields that will show on each users profile.', 'buddypress' ) . '<br /><br />' . __( 'Note: Drag fields from other groups and drop them on the "Signup Fields" tab to include them into your registration form.', 'buddypress' ); 776 break; 777 778 default: 779 $retval = false; 780 break; 781 } 782 783 // Wrap text in a paragraph tag. 784 if ( ! empty( $retval ) ) { 785 $retval = '<p>' . $retval . '</p>'; 786 } 787 788 return $retval; 789 } 790 791 /** Separator *****************************************************************/ 792 793 /** 794 * Add a separator to the WordPress admin menus. 795 * 796 * @since 1.7.0 797 */ 798 function bp_admin_separator() { 799 800 // Bail if BuddyPress is not network activated and viewing network admin. 801 if ( is_network_admin() && ! bp_is_network_activated() ) { 802 return; 803 } 804 805 // Bail if BuddyPress is network activated and viewing site admin. 806 if ( ! is_network_admin() && bp_is_network_activated() ) { 807 return; 808 } 809 810 // Prevent duplicate separators when no core menu items exist. 811 if ( ! bp_current_user_can( 'bp_moderate' ) ) { 812 return; 813 } 814 815 // Bail if there are no components with admin UI's. Hardcoded for now, until 816 // there's a real API for determining this later. 817 if ( ! bp_is_active( 'activity' ) && ! bp_is_active( 'groups' ) ) { 818 return; 819 } 820 821 global $menu; 822 823 $menu[] = array( '', 'read', 'separator-buddypress', '', 'wp-menu-separator buddypress' ); 824 } 825 826 /** 827 * Tell WordPress we have a custom menu order. 828 * 829 * @since 1.7.0 830 * 831 * @param bool $menu_order Menu order. 832 * @return bool Always true. 833 */ 834 function bp_admin_custom_menu_order( $menu_order = false ) { 835 836 // Bail if user cannot see admin pages. 837 if ( ! bp_current_user_can( 'bp_moderate' ) ) { 838 return $menu_order; 839 } 840 841 return true; 842 } 843 844 /** 845 * Move our custom separator above our custom post types. 846 * 847 * @since 1.7.0 848 * 849 * @param array $menu_order Menu Order. 850 * @return array Modified menu order. 851 */ 852 function bp_admin_menu_order( $menu_order = array() ) { 853 854 // Bail if user cannot see admin pages. 855 if ( empty( $menu_order ) || ! bp_current_user_can( 'bp_moderate' ) ) { 856 return $menu_order; 857 } 858 859 // Initialize our custom order array. 860 $bp_menu_order = array(); 861 862 // Menu values. 863 $last_sep = is_network_admin() ? 'separator1' : 'separator2'; 864 865 /** 866 * Filters the custom admin menus. 867 * 868 * @since 1.7.0 869 * 870 * @param array $value Empty array. 871 */ 872 $custom_menus = (array) apply_filters( 'bp_admin_menu_order', array() ); 873 874 // Bail if no components have top level admin pages. 875 if ( empty( $custom_menus ) ) { 876 return $menu_order; 877 } 878 879 // Add our separator to beginning of array. 880 array_unshift( $custom_menus, 'separator-buddypress' ); 881 882 // Loop through menu order and do some rearranging. 883 foreach ( (array) $menu_order as $item ) { 884 885 // Position BuddyPress menus above appearance. 886 if ( $last_sep == $item ) { 887 888 // Add our custom menus. 889 foreach ( (array) $custom_menus as $custom_menu ) { 890 if ( array_search( $custom_menu, $menu_order ) ) { 891 $bp_menu_order[] = $custom_menu; 892 } 893 } 894 895 // Add the appearance separator. 896 $bp_menu_order[] = $last_sep; 897 898 // Skip our menu items. 899 } elseif ( ! in_array( $item, $custom_menus ) ) { 900 $bp_menu_order[] = $item; 901 } 902 } 903 904 // Return our custom order. 905 return $bp_menu_order; 906 } 907 908 /** Utility *****************************************************************/ 909 910 /** 911 * When using a WP_List_Table, get the currently selected bulk action. 912 * 913 * WP_List_Tables have bulk actions at the top and at the bottom of the tables, 914 * and the inputs have different keys in the $_REQUEST array. This function 915 * reconciles the two values and returns a single action being performed. 916 * 917 * @since 1.7.0 918 * 919 * @return string 920 */ 921 function bp_admin_list_table_current_bulk_action() { 922 923 $action = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : ''; 924 925 // If the bottom is set, let it override the action. 926 if ( ! empty( $_REQUEST['action2'] ) && $_REQUEST['action2'] != '-1' ) { 927 $action = $_REQUEST['action2']; 928 } 929 930 return $action; 931 } 932 933 /** Menus *********************************************************************/ 934 935 /** 936 * Register meta box and associated JS for BuddyPress WP Nav Menu. 937 * 938 * @since 1.9.0 939 */ 940 function bp_admin_wp_nav_menu_meta_box() { 941 if ( ! bp_is_root_blog() ) { 942 return; 943 } 944 945 add_meta_box( 'add-buddypress-nav-menu', __( 'BuddyPress Member', 'buddypress' ), 'bp_admin_do_wp_nav_menu_meta_box', 'nav-menus', 'side', 'default' ); 946 947 add_action( 'admin_print_footer_scripts', 'bp_admin_wp_nav_menu_restrict_items' ); 948 } 949 950 /** 951 * BP Member nav menu filter to short-circuit WP's query. 952 * 953 * @since 7.0.0 954 * 955 * @param null $null A null value. 956 * @param WP_Query $wp_query The WP_Query instance (passed by reference). 957 * @return array The BP Member nav items to short-circuit WP's query, 958 */ 959 function bp_admin_get_wp_nav_menu_items( $null, $wp_query ) { 960 if ( isset( $wp_query->query['orderby'], $wp_query->query['order'] ) && 'post_date' === $wp_query->query['orderby'] && 'DESC' === $wp_query->query['order'] ) { 961 return bp_nav_menu_get_loggedin_pages(); 962 } elseif ( isset( $wp_query->query['nopaging'] ) && true === $wp_query->query['nopaging'] ) { 963 return array_merge( bp_nav_menu_get_loggedin_pages(), bp_nav_menu_get_loggedout_pages() ); 964 } 965 966 return bp_nav_menu_get_loggedout_pages(); 967 } 968 969 /** 970 * Build and populate the BuddyPress accordion on Appearance > Menus. 971 * 972 * @since 1.9.0 973 * @since 7.0.0 Uses wp_nav_menu_item_post_type_meta_box() 974 * 975 * @global $nav_menu_selected_id 976 */ 977 function bp_admin_do_wp_nav_menu_meta_box( $object = '', $box = array() ) { 978 global $nav_menu_selected_id; 979 980 $box['args'] = (object) array( 981 'name' => 'bp_nav_menu_item', 982 '_default_query' => array(), 983 ); 984 985 // Temporarly register a post type. 986 register_post_type( 987 'bp_nav_menu_item', 988 array( 989 'label' => 'BuddyPress', 990 'labels' => array( 991 'search_items' => __( 'Search BuddyPress member menu items', 'buddypress' ), 992 'all_items' => __( 'All BuddyPress Member menu items', 'buddypress' ), 993 ), 994 'public' => true, 995 'hierarchical' => false, 996 'has_archive' => false, 997 'rewrite' => false, 998 ) 999 ); 1000 1001 // Temporarly override the posts query results. 1002 add_filter( 'posts_pre_query', 'bp_admin_get_wp_nav_menu_items', 10, 2 ); 1003 1004 ob_start(); 1005 wp_nav_menu_item_post_type_meta_box( 'buddypress', $box ); 1006 $output = ob_get_clean(); 1007 1008 $get_bp_items = new WP_Query; 1009 $all_bp_items = $get_bp_items->query( array( 'nopaging' => true ) ); 1010 $walker = new Walker_Nav_Menu_Checklist(); 1011 $all_bp_tabs = sprintf( 1012 '<div id="bp_nav_menu_item-all" class="tabs-panel tabs-panel-view-all tabs-panel-inactive" role="region" aria-label="%1$s" tabindex="0"> 1013 <ul id="bp_nav_menu_itemchecklist" data-wp-lists="list:bp_nav_menu_item" class="categorychecklist form-no-clear"> 1014 %2$s 1015 </ul> 1016 </div>', 1017 esc_html__( 'All BuddyPress Member menu items', 'buddypress' ), 1018 walk_nav_menu_tree( array_map( 'wp_setup_nav_menu_item', $all_bp_items ), 0, (object) array( 'walker' => $walker ) ) 1019 ); 1020 1021 // Remove temporary post type and filter. 1022 unregister_post_type( 'bp_nav_menu_item' ); 1023 remove_filter( 'posts_pre_query', 'bp_admin_get_wp_nav_menu_items', 10, 2 ); 1024 1025 $tab_name = 'bp_nav_menu_item-tab'; 1026 $current_tab = 'logged-in'; 1027 $tabs = array( 1028 'logged-in' => __( 'Logged-In', 'buddypress' ), 1029 'logged-out' => __( 'Logged-Out', 'buddypress' ), 1030 'all' => __( 'All', 'buddypress' ), 1031 ); 1032 $tab_urls = array( 1033 'all' => '', 1034 'logged-in' => '', 1035 'logged-out' => '', 1036 ); 1037 1038 if ( isset( $_REQUEST[ $tab_name ] ) && in_array( $_REQUEST[ $tab_name ], array_keys( $tabs ), true ) ) { 1039 $current_tab = $_REQUEST[ $tab_name ]; 1040 } 1041 1042 $removed_args = array( 1043 'action', 1044 'customlink-tab', 1045 'edit-menu-item', 1046 'menu-item', 1047 'page-tab', 1048 '_wpnonce', 1049 ); 1050 1051 if ( $nav_menu_selected_id ) { 1052 $tab_urls['all'] = esc_url( add_query_arg( $tab_name, 'all', remove_query_arg( $removed_args ) ) ); 1053 $tab_urls['logged-in'] = esc_url( add_query_arg( $tab_name, 'logged-in', remove_query_arg( $removed_args ) ) ); 1054 $tab_urls['logged-out'] = esc_url( add_query_arg( $tab_name, 'logged-out', remove_query_arg( $removed_args ) ) ); 1055 } 1056 1057 $bp_tabs_nav = ''; 1058 foreach ( $tabs as $tab => $tab_text ) { 1059 $class = ''; 1060 $datatype = 'bp_nav_menu_item-' . $tab; 1061 1062 if ( $current_tab === $tab ) { 1063 $class = ' class="tabs"'; 1064 } 1065 1066 if ( 'all' !== $tab ) { 1067 $datatype = 'tabs-panel-posttype-bp_nav_menu_item-' . $tab; 1068 } 1069 1070 $bp_tabs_nav .= sprintf( 1071 '<li%1$s> 1072 <a class="nav-tab-link" data-type="%2$s" href="%3$s"> 1073 %4$s 1074 </a> 1075 </li>', 1076 $class, 1077 $datatype, 1078 esc_url( $tab_urls[ $tab ] ) . '#' . $datatype, 1079 esc_html( $tab_text ) 1080 ); 1081 } 1082 1083 $output = str_replace( 1084 array( 1085 'tabs-panel-posttype-bp_nav_menu_item-most-recent', 1086 'bp_nav_menu_itemchecklist-most-recent', 1087 'bp_nav_menu_item-all', 1088 'bp_nav_menu_itemchecklist', 1089 ), 1090 array( 1091 'tabs-panel-posttype-bp_nav_menu_item-logged-in', 1092 'bp_nav_menu_itemchecklist-logged-in', 1093 'tabs-panel-posttype-bp_nav_menu_item-logged-out', 1094 'bp_nav_menu_itemchecklist-logged-out', 1095 ), 1096 $output 1097 ); 1098 1099 preg_match( '/\<ul\sid=\"posttype-bp_nav_menu_item-tabs\"[^>]*>(.*?)\<\/ul\>\<!-- \.posttype-tabs --\>/s', $output, $tabs_nav ); 1100 1101 if ( isset( $tabs_nav[1] ) ) { 1102 $output = str_replace( $tabs_nav[1], $bp_tabs_nav, $output ); 1103 } 1104 1105 echo preg_replace( '/\<div\sclass=\".*\"\sid=\"tabs-panel-posttype-bp_nav_menu_item-search\"[^>]*>(.*?)\<\/div\>/s', $all_bp_tabs, $output ); 1106 } 1107 1108 /** 1109 * In admin emails list, for non-en_US locales, add notice explaining how to reinstall emails. 1110 * 1111 * If BuddyPress installs before its translations are in place, tell people how to reinstall 1112 * the emails so they have their contents in their site's language. 1113 * 1114 * @since 2.5.0 1115 */ 1116 function bp_admin_email_maybe_add_translation_notice() { 1117 if ( get_current_screen()->post_type !== bp_get_email_post_type() || get_locale() === 'en_US' ) { 1118 return; 1119 } 1120 1121 // If user can't access BP Tools, there's no point showing the message. 1122 if ( ! current_user_can( buddypress()->admin->capability ) ) { 1123 return; 1124 } 1125 1126 if ( bp_core_do_network_admin() ) { 1127 $admin_page = 'admin.php'; 1128 } else { 1129 $admin_page = 'tools.php'; 1130 } 1131 1132 bp_core_add_admin_notice( 1133 sprintf( 1134 // Translators: %s is the url to the BuddyPress tools administration screen. 1135 __( 'Are these emails not written in your site\'s language? Go to <a href="%s">BuddyPress Tools and try the "reinstall emails"</a> tool.', 'buddypress' ), 1136 esc_url( add_query_arg( 'page', 'bp-tools', bp_get_admin_url( $admin_page ) ) ) 1137 ), 1138 'updated' 1139 ); 1140 } 1141 add_action( 'admin_head-edit.php', 'bp_admin_email_maybe_add_translation_notice' ); 1142 1143 /** 1144 * In emails editor, add notice linking to token documentation on Codex. 1145 * 1146 * @since 2.5.0 1147 */ 1148 function bp_admin_email_add_codex_notice() { 1149 if ( get_current_screen()->post_type !== bp_get_email_post_type() ) { 1150 return; 1151 } 1152 1153 bp_core_add_admin_notice( 1154 sprintf( 1155 // Translators: %s is the url to the BuddyPress codex page about BP Email tokens. 1156 __( 'Phrases wrapped in braces <code>{{ }}</code> are email tokens. <a href="%s">Learn about tokens on the BuddyPress Codex</a>.', 'buddypress' ), 1157 esc_url( 'https://codex.buddypress.org/emails/email-tokens/' ) 1158 ), 1159 'error' 1160 ); 1161 } 1162 add_action( 'admin_head-post.php', 'bp_admin_email_add_codex_notice' ); 1163 1164 /** 1165 * Display metabox for email taxonomy type. 1166 * 1167 * Shows the term description in a list, rather than the term name itself. 1168 * 1169 * @since 2.5.0 1170 * 1171 * @param WP_Post $post Post object. 1172 * @param array $box { 1173 * Tags meta box arguments. 1174 * 1175 * @type string $id Meta box ID. 1176 * @type string $title Meta box title. 1177 * @type callable $callback Meta box display callback. 1178 * } 1179 */ 1180 function bp_email_tax_type_metabox( $post, $box ) { 1181 $r = array( 1182 'taxonomy' => bp_get_email_tax_type(), 1183 ); 1184 1185 $tax_name = esc_attr( $r['taxonomy'] ); 1186 $taxonomy = get_taxonomy( $r['taxonomy'] ); 1187 ?> 1188 <div id="taxonomy-<?php echo $tax_name; ?>" class="categorydiv"> 1189 <div id="<?php echo $tax_name; ?>-all" class="tabs-panel"> 1190 <?php 1191 $name = ( $tax_name == 'category' ) ? 'post_category' : 'tax_input[' . $tax_name . ']'; 1192 echo "<input type='hidden' name='{$name}[]' value='0' />"; // Allows for an empty term set to be sent. 0 is an invalid Term ID and will be ignored by empty() checks. 1193 ?> 1194 <ul id="<?php echo $tax_name; ?>checklist" data-wp-lists="list:<?php echo $tax_name; ?>" class="categorychecklist form-no-clear"> 1195 <?php 1196 wp_terms_checklist( 1197 $post->ID, 1198 array( 1199 'taxonomy' => $tax_name, 1200 'walker' => new BP_Walker_Category_Checklist(), 1201 ) 1202 ); 1203 ?> 1204 </ul> 1205 </div> 1206 1207 <p><?php esc_html_e( 'Choose when this email will be sent.', 'buddypress' ); ?></p> 1208 </div> 1209 <?php 1210 } 1211 1212 /** 1213 * Custom metaboxes used by our 'bp-email' post type. 1214 * 1215 * @since 2.5.0 1216 */ 1217 function bp_email_custom_metaboxes() { 1218 // Remove default 'Excerpt' metabox and replace with our own. 1219 remove_meta_box( 'postexcerpt', null, 'normal' ); 1220 add_meta_box( 'postexcerpt', __( 'Plain text email content', 'buddypress' ), 'bp_email_plaintext_metabox', null, 'normal', 'high' ); 1221 } 1222 add_action( 'add_meta_boxes_' . bp_get_email_post_type(), 'bp_email_custom_metaboxes' ); 1223 1224 /** 1225 * Customized version of the 'Excerpt' metabox for our 'bp-email' post type. 1226 * 1227 * We are using the 'Excerpt' metabox as our plain-text email content editor. 1228 * 1229 * @since 2.5.0 1230 * 1231 * @param WP_Post $post 1232 */ 1233 function bp_email_plaintext_metabox( $post ) { 1234 ?> 1235 1236 <label class="screen-reader-text" for="excerpt"> 1237 <?php 1238 /* translators: accessibility text */ 1239 _e( 'Plain text email content', 'buddypress' ); 1240 ?> 1241 </label><textarea rows="5" cols="40" name="excerpt" id="excerpt"><?php echo $post->post_excerpt; // textarea_escaped ?></textarea> 1242 1243 <p><?php _e( 'Most email clients support HTML email. However, some people prefer to receive plain text email. Enter a plain text alternative version of your email here.', 'buddypress' ); ?></p> 1244 1245 <?php 1246 } 1247 1248 /** 1249 * Restrict various items from view if editing a BuddyPress menu. 1250 * 1251 * If a person is editing a BP menu item, that person should not be able to 1252 * see or edit the following fields: 1253 * 1254 * - CSS Classes - We use the 'bp-menu' CSS class to determine if the 1255 * menu item belongs to BP, so we cannot allow manipulation of this field to 1256 * occur. 1257 * - URL - This field is automatically generated by BP on output, so this 1258 * field is useless and can cause confusion. 1259 * 1260 * Note: These restrictions are only enforced if JavaScript is enabled. 1261 * 1262 * @since 1.9.0 1263 */ 1264 function bp_admin_wp_nav_menu_restrict_items() { 1265 ?> 1266 <script type="text/javascript"> 1267 jQuery( '#menu-to-edit').on( 'click', 'a.item-edit', function() { 1268 var settings = jQuery(this).closest( '.menu-item-bar' ).next( '.menu-item-settings' ); 1269 var css_class = settings.find( '.edit-menu-item-classes' ); 1270 1271 if( css_class.val().indexOf( 'bp-menu' ) === 0 ) { 1272 css_class.attr( 'readonly', 'readonly' ); 1273 settings.find( '.field-url' ).css( 'display', 'none' ); 1274 } 1275 }); 1276 </script> 1277 <?php 1278 } 1279 1280 /** 1281 * Add "Mark as Spam/Ham" button to user row actions. 1282 * 1283 * @since 2.0.0 1284 * 1285 * @param array $actions User row action links. 1286 * @param object $user_object Current user information. 1287 * @return array $actions User row action links. 1288 */ 1289 function bp_core_admin_user_row_actions( $actions, $user_object ) { 1290 1291 // Setup the $user_id variable from the current user object. 1292 $user_id = 0; 1293 if ( ! empty( $user_object->ID ) ) { 1294 $user_id = absint( $user_object->ID ); 1295 } 1296 1297 // Bail early if user cannot perform this action, or is looking at themselves. 1298 if ( current_user_can( 'edit_user', $user_id ) && ( bp_loggedin_user_id() !== $user_id ) ) { 1299 1300 // Admin URL could be single site or network. 1301 $url = bp_get_admin_url( 'users.php' ); 1302 1303 // If spammed, create unspam link. 1304 if ( bp_is_user_spammer( $user_id ) ) { 1305 $url = add_query_arg( 1306 array( 1307 'action' => 'ham', 1308 'user' => $user_id, 1309 ), 1310 $url 1311 ); 1312 $unspam_link = wp_nonce_url( $url, 'bp-spam-user' ); 1313 $actions['ham'] = sprintf('<a href="%1$s">%2$s</a>', esc_url( $unspam_link ), esc_html__( 'Not Spam', 'buddypress' ) ); 1314 1315 // If not already spammed, create spam link. 1316 } else { 1317 $url = add_query_arg( 1318 array( 1319 'action' => 'spam', 1320 'user' => $user_id, 1321 ), 1322 $url 1323 ); 1324 $spam_link = wp_nonce_url( $url, 'bp-spam-user' ); 1325 $actions['spam'] = sprintf( '<a class="submitdelete" href="%1$s">%2$s</a>', esc_url( $spam_link ), esc_html__( 'Spam', 'buddypress' ) ); 1326 } 1327 } 1328 1329 // Create a "View" link. 1330 $url = bp_core_get_user_domain( $user_id ); 1331 $actions['view'] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $url ), esc_html__( 'View', 'buddypress' ) ); 1332 1333 // Return new actions. 1334 return $actions; 1335 } 1336 1337 /** 1338 * Catch requests to mark individual users as spam/ham from users.php. 1339 * 1340 * @since 2.0.0 1341 */ 1342 function bp_core_admin_user_manage_spammers() { 1343 1344 // Print our inline scripts on non-Multisite. 1345 add_action( 'admin_footer', 'bp_core_admin_user_spammed_js' ); 1346 1347 $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : false; 1348 $updated = isset( $_REQUEST['updated'] ) ? $_REQUEST['updated'] : false; 1349 $mode = isset( $_POST['mode'] ) ? $_POST['mode'] : false; 1350 1351 // If this is a multisite, bulk request, stop now! 1352 if ( 'list' == $mode ) { 1353 return; 1354 } 1355 1356 // Process a spam/ham request. 1357 if ( ! empty( $action ) && in_array( $action, array( 'spam', 'ham' ) ) ) { 1358 1359 check_admin_referer( 'bp-spam-user' ); 1360 1361 $user_id = ! empty( $_REQUEST['user'] ) ? intval( $_REQUEST['user'] ) : false; 1362 1363 if ( empty( $user_id ) ) { 1364 return; 1365 } 1366 1367 $redirect = wp_get_referer(); 1368 1369 $status = ( $action == 'spam' ) ? 'spam' : 'ham'; 1370 1371 // Process the user. 1372 bp_core_process_spammer_status( $user_id, $status ); 1373 1374 $redirect = add_query_arg( array( 'updated' => 'marked-' . $status ), $redirect ); 1375 1376 wp_redirect( $redirect ); 1377 } 1378 1379 // Display feedback. 1380 if ( ! empty( $updated ) && in_array( $updated, array( 'marked-spam', 'marked-ham' ) ) ) { 1381 1382 if ( 'marked-spam' === $updated ) { 1383 $notice = __( 'User marked as spammer. Spam users are visible only to site admins.', 'buddypress' ); 1384 } else { 1385 $notice = __( 'User removed from spam.', 'buddypress' ); 1386 } 1387 1388 bp_core_add_admin_notice( $notice ); 1389 } 1390 } 1391 1392 /** 1393 * Inline script that adds the 'site-spammed' class to spammed users. 1394 * 1395 * @since 2.0.0 1396 */ 1397 function bp_core_admin_user_spammed_js() { 1398 ?> 1399 <script type="text/javascript"> 1400 jQuery( document ).ready( function($) { 1401 $( '.row-actions .ham' ).each( function() { 1402 $( this ).closest( 'tr' ).addClass( 'site-spammed' ); 1403 }); 1404 }); 1405 </script> 1406 <?php 1407 } 1408 1409 /** 1410 * Catch and process an admin notice dismissal. 1411 * 1412 * @since 2.7.0 1413 */ 1414 function bp_core_admin_notice_dismiss_callback() { 1415 if ( ! current_user_can( 'install_plugins' ) ) { 1416 wp_send_json_error(); 1417 } 1418 1419 $nonce_data = array(); 1420 if ( isset( $_SERVER['HTTP_X_BP_NONCE'] ) ) { 1421 $nonce_data = array( 1422 'nonce' => $_SERVER['HTTP_X_BP_NONCE'], 1423 'action' => 'bp_dismiss_admin_notice', 1424 ); 1425 } elseif ( isset( $_POST['nonce'] ) ) { 1426 $nonce_data['nonce'] = $_POST['nonce']; 1427 } 1428 1429 if ( empty( $nonce_data['nonce'] ) || empty( $_POST['notice_id'] ) ) { 1430 wp_send_json_error(); 1431 } 1432 1433 $notice_id = wp_unslash( $_POST['notice_id'] ); 1434 if ( ! isset( $nonce_data['action'] ) ) { 1435 $nonce_data['action'] = 'bp-dismissible-notice-' . $notice_id; 1436 } 1437 1438 if ( ! wp_verify_nonce( $nonce_data['nonce'], $nonce_data['action'] ) ) { 1439 wp_send_json_error(); 1440 } 1441 1442 bp_update_option( "bp-dismissed-notice-{$notice_id}", true ); 1443 1444 wp_send_json_success(); 1445 } 1446 add_action( 'wp_ajax_bp_dismiss_notice', 'bp_core_admin_notice_dismiss_callback' ); 1447 1448 /** 1449 * Add a "buddypress" class to body element of wp-admin. 1450 * 1451 * @since 2.8.0 1452 * 1453 * @param string $classes CSS classes for the body tag in the admin, a space separated string. 1454 * 1455 * @return string 1456 */ 1457 function bp_core_admin_body_classes( $classes ) { 1458 $bp = buddypress(); 1459 1460 $bp_class = ' buddypress'; 1461 if ( isset( $bp->admin->nav_tabs ) && $bp->admin->nav_tabs ) { 1462 $bp_class .= ' bp-is-tabbed-screen'; 1463 } 1464 1465 return $classes . $bp_class; 1466 } 1467 add_filter( 'admin_body_class', 'bp_core_admin_body_classes' ); 1468 1469 /** 1470 * Adds a BuddyPress category to house BuddyPress blocks. 1471 * 1472 * @since 5.0.0 1473 * @since 8.0.0 The `bp_block_category_post_types` filter has been deprecated. 1474 * 1475 * @param array $categories Array of block categories. 1476 * @param string|WP_Post $post Post being loaded. 1477 */ 1478 function bp_block_category( $categories = array(), $editor_name_or_post = null ) { 1479 if ( $editor_name_or_post instanceof WP_Post ) { 1480 $post_types = array( 'post', 'page' ); 1481 1482 /* 1483 * As blocks are always loaded even if the category is not available, there's no more interest 1484 * in disabling the BuddyPress category. 1485 */ 1486 apply_filters_deprecated( 'bp_block_category_post_types', array( $post_types ), '8.0.0' ); 1487 } 1488 1489 return array_merge( 1490 $categories, 1491 array( 1492 array( 1493 'slug' => 'buddypress', 1494 'title' => __( 'BuddyPress', 'buddypress' ), 1495 'icon' => 'buddicons-buddypress-logo', 1496 ), 1497 ) 1498 ); 1499 } 1500 1501 /** 1502 * Select the right `block_categories` filter according to WP version. 1503 * 1504 * @since 8.0.0 1505 */ 1506 function bp_block_init_category_filter() { 1507 if ( function_exists( 'get_default_block_categories' ) ) { 1508 add_filter( 'block_categories_all', 'bp_block_category', 1, 2 ); 1509 } else { 1510 add_filter( 'block_categories', 'bp_block_category', 1, 2 ); 1511 } 1512 } 1513 add_action( 'bp_init', 'bp_block_init_category_filter' );
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 |