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


Generated: Tue Nov 19 01:01:36 2019 Cross-referenced by PHPXref 0.7.1