[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-core/admin/ -> bp-core-admin-functions.php (source)

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


Generated: Tue Dec 1 01:01:37 2020 Cross-referenced by PHPXref 0.7.1