[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-core/ -> bp-core-filters.php (source)

   1  <?php
   2  /**
   3   * BuddyPress Filters.
   4   *
   5   * This file contains the filters that are used throughout BuddyPress. They are
   6   * consolidated here to make searching for them easier, and to help developers
   7   * understand at a glance the order in which things occur.
   8   *
   9   * There are a few common places that additional filters can currently be found.
  10   *
  11   *  - BuddyPress: In {@link BuddyPress::setup_actions()} in buddypress.php
  12   *  - Component: In {@link BP_Component::setup_actions()} in
  13   *                bp-core/bp-core-component.php
  14   *  - Admin: More in {@link BP_Admin::setup_actions()} in
  15   *            bp-core/bp-core-admin.php
  16   *
  17   * @package BuddyPress
  18   * @subpackage Core
  19   * @since 1.5.0
  20   *
  21   * @see bp-core-actions.php
  22   */
  23  
  24  // Exit if accessed directly.
  25  defined( 'ABSPATH' ) || exit;
  26  
  27  /**
  28   * Attach BuddyPress to WordPress.
  29   *
  30   * BuddyPress uses its own internal actions to help aid in third-party plugin
  31   * development, and to limit the amount of potential future code changes when
  32   * updates to WordPress core occur.
  33   *
  34   * These actions exist to create the concept of 'plugin dependencies'. They
  35   * provide a safe way for plugins to execute code *only* when BuddyPress is
  36   * installed and activated, without needing to do complicated guesswork.
  37   *
  38   * For more information on how this works, see the 'Plugin Dependency' section
  39   * near the bottom of this file.
  40   *
  41   *           v--WordPress Actions       v--BuddyPress Sub-actions
  42   */
  43  add_filter( 'request',                 'bp_request',             10    );
  44  add_filter( 'template_include',        'bp_template_include',    10    );
  45  add_filter( 'login_redirect',          'bp_login_redirect',      10, 3 );
  46  add_filter( 'map_meta_cap',            'bp_map_meta_caps',       10, 4 );
  47  
  48  // Add some filters to feedback messages.
  49  add_filter( 'bp_core_render_message_content', 'wptexturize'       );
  50  add_filter( 'bp_core_render_message_content', 'convert_smilies'   );
  51  add_filter( 'bp_core_render_message_content', 'convert_chars'     );
  52  add_filter( 'bp_core_render_message_content', 'wpautop'           );
  53  add_filter( 'bp_core_render_message_content', 'shortcode_unautop' );
  54  add_filter( 'bp_core_render_message_content', 'wp_kses_data', 5   );
  55  
  56  // Emails.
  57  add_filter( 'bp_email_set_content_html', 'wp_filter_post_kses', 6 );
  58  add_filter( 'bp_email_set_content_html', 'stripslashes', 8 );
  59  add_filter( 'bp_email_set_content_plaintext', 'wp_strip_all_tags', 6 );
  60  add_filter( 'bp_email_set_subject', 'sanitize_text_field', 6 );
  61  
  62  /**
  63   * Template Compatibility.
  64   *
  65   * If you want to completely bypass this and manage your own custom BuddyPress
  66   * template hierarchy, start here by removing this filter, then look at how
  67   * bp_template_include() works and do something similar. :)
  68   */
  69  add_filter( 'bp_template_include',   'bp_template_include_theme_supports', 2, 1 );
  70  add_filter( 'bp_template_include',   'bp_template_include_theme_compat',   4, 2 );
  71  
  72  // Filter BuddyPress template locations.
  73  add_filter( 'bp_get_template_stack', 'bp_add_template_stack_locations' );
  74  
  75  // Turn comments off for BuddyPress pages.
  76  add_filter( 'comments_open', 'bp_comments_open', 10, 2 );
  77  
  78  // Prevent DB query for WP's main loop.
  79  add_filter( 'posts_pre_query', 'bp_core_filter_wp_query', 10, 2 );
  80  
  81  /**
  82   * Prevent specific pages (eg 'Activate') from showing on page listings.
  83   *
  84   * @since 1.5.0
  85   *
  86   * @param array $pages List of excluded page IDs, as passed to the
  87   *                     'wp_list_pages_excludes' filter.
  88   * @return array The exclude list, with BP's pages added.
  89   */
  90  function bp_core_exclude_pages( $pages = array() ) {
  91  
  92      // Bail if not the root blog.
  93      if ( ! bp_is_root_blog() )
  94          return $pages;
  95  
  96      $bp = buddypress();
  97  
  98      if ( !empty( $bp->pages->activate ) )
  99          $pages[] = $bp->pages->activate->id;
 100  
 101      if ( !empty( $bp->pages->register ) )
 102          $pages[] = $bp->pages->register->id;
 103  
 104      /**
 105       * Filters specific pages that shouldn't show up on page listings.
 106       *
 107       * @since 1.5.0
 108       *
 109       * @param array $pages Array of pages to exclude.
 110       */
 111      return apply_filters( 'bp_core_exclude_pages', $pages );
 112  }
 113  add_filter( 'wp_list_pages_excludes', 'bp_core_exclude_pages' );
 114  
 115  /**
 116   * Prevent specific pages (eg 'Activate') from showing in the Pages meta box of the Menu Administration screen.
 117   *
 118   * @since 2.0.0
 119   *
 120   * @param object|null $object The post type object used in the meta box.
 121   * @return object|null The $object, with a query argument to remove register and activate pages id.
 122   */
 123  function bp_core_exclude_pages_from_nav_menu_admin( $object = null ) {
 124  
 125      // Bail if not the root blog.
 126      if ( ! bp_is_root_blog() ) {
 127          return $object;
 128      }
 129  
 130      if ( 'page' != $object->name ) {
 131          return $object;
 132      }
 133  
 134      $bp = buddypress();
 135      $pages = array();
 136  
 137      if ( ! empty( $bp->pages->activate ) ) {
 138          $pages[] = $bp->pages->activate->id;
 139      }
 140  
 141      if ( ! empty( $bp->pages->register ) ) {
 142          $pages[] = $bp->pages->register->id;
 143      }
 144  
 145      if ( ! empty( $pages ) ) {
 146          $object->_default_query['post__not_in'] = $pages;
 147      }
 148  
 149      return $object;
 150  }
 151  add_filter( 'nav_menu_meta_box_object', 'bp_core_exclude_pages_from_nav_menu_admin', 11, 1 );
 152  
 153  /**
 154   * Adds current page CSS classes to the parent BP page in a WP Page Menu.
 155   *
 156   * Because BuddyPress primarily uses virtual pages, we need a way to highlight
 157   * the BP parent page during WP menu generation.  This function checks the
 158   * current BP component against the current page in the WP menu to see if we
 159   * should highlight the WP page.
 160   *
 161   * @since 2.2.0
 162   *
 163   * @param array   $retval CSS classes for the current menu page in the menu.
 164   * @param WP_Post $page   The page properties for the current menu item.
 165   * @return array
 166   */
 167  function bp_core_menu_highlight_parent_page( $retval, $page ) {
 168      if ( ! is_buddypress() ) {
 169          return $retval;
 170      }
 171  
 172      $page_id = false;
 173  
 174      // Loop against all BP component pages.
 175      foreach ( (array) buddypress()->pages as $component => $bp_page ) {
 176          // Handles the majority of components.
 177          if ( bp_is_current_component( $component ) ) {
 178              $page_id = (int) $bp_page->id;
 179          }
 180  
 181          // Stop if not on a user page.
 182          if ( ! bp_is_user() && ! empty( $page_id ) ) {
 183              break;
 184          }
 185  
 186          // Members component requires an explicit check due to overlapping components.
 187          if ( bp_is_user() && 'members' === $component ) {
 188              $page_id = (int) $bp_page->id;
 189              break;
 190          }
 191      }
 192  
 193      // Duplicate some logic from Walker_Page::start_el() to highlight menu items.
 194      if ( ! empty( $page_id ) ) {
 195          $_bp_page = get_post( $page_id );
 196          if ( in_array( $page->ID, $_bp_page->ancestors, true ) ) {
 197              $retval[] = 'current_page_ancestor';
 198          }
 199          if ( $page->ID === $page_id ) {
 200              $retval[] = 'current_page_item';
 201          } elseif ( $_bp_page && $page->ID === $_bp_page->post_parent ) {
 202              $retval[] = 'current_page_parent';
 203          }
 204      }
 205  
 206      $retval = array_unique( $retval );
 207  
 208      return $retval;
 209  }
 210  add_filter( 'page_css_class', 'bp_core_menu_highlight_parent_page', 10, 2 );
 211  
 212  /**
 213   * Adds current page CSS classes to the parent BP page in a WP Nav Menu.
 214   *
 215   * When {@link wp_nav_menu()} is used, this function helps to highlight the
 216   * current BP parent page during nav menu generation.
 217   *
 218   * @since 2.2.0
 219   *
 220   * @param array   $retval CSS classes for the current nav menu item in the menu.
 221   * @param WP_Post $item   The properties for the current nav menu item.
 222   * @return array
 223   */
 224  function bp_core_menu_highlight_nav_menu_item( $retval, $item ) {
 225      // If we're not on a BP page or if the current nav item is not a page, stop!
 226      if ( ! is_buddypress() || 'page' !== $item->object ) {
 227          return $retval;
 228      }
 229  
 230      // Get the WP page.
 231      $page   = get_post( $item->object_id );
 232  
 233      // See if we should add our highlight CSS classes for the page.
 234      $retval = bp_core_menu_highlight_parent_page( $retval, $page );
 235  
 236      return $retval;
 237  }
 238  add_filter( 'nav_menu_css_class', 'bp_core_menu_highlight_nav_menu_item', 10, 2 );
 239  
 240  /**
 241   * Filter the blog post comments array and insert BuddyPress URLs for users.
 242   *
 243   * @since 1.2.0
 244   *
 245   * @param array $comments The array of comments supplied to the comments template.
 246   * @param int   $post_id  The post ID.
 247   * @return array $comments The modified comment array.
 248   */
 249  function bp_core_filter_comments( $comments, $post_id ) {
 250      global $wpdb;
 251  
 252      foreach( (array) $comments as $comment ) {
 253          if ( $comment->user_id )
 254              $user_ids[] = $comment->user_id;
 255      }
 256  
 257      if ( empty( $user_ids ) )
 258          return $comments;
 259  
 260      $user_ids = implode( ',', wp_parse_id_list( $user_ids ) );
 261  
 262      if ( !$userdata = $wpdb->get_results( "SELECT ID as user_id, user_login, user_nicename FROM {$wpdb->users} WHERE ID IN ({$user_ids})" ) )
 263          return $comments;
 264  
 265      foreach( (array) $userdata as $user )
 266          $users[$user->user_id] = bp_core_get_user_domain( $user->user_id, $user->user_nicename, $user->user_login );
 267  
 268      foreach( (array) $comments as $i => $comment ) {
 269          if ( !empty( $comment->user_id ) ) {
 270              if ( !empty( $users[$comment->user_id] ) )
 271                  $comments[$i]->comment_author_url = $users[$comment->user_id];
 272          }
 273      }
 274  
 275      return $comments;
 276  }
 277  add_filter( 'comments_array', 'bp_core_filter_comments', 10, 2 );
 278  
 279  /**
 280   * When a user logs in, redirect him in a logical way.
 281   *
 282   * @since 1.2.0
 283   *
 284   *       are redirected to on login.
 285   *
 286   * @param string  $redirect_to     The URL to be redirected to, sanitized in wp-login.php.
 287   * @param string  $redirect_to_raw The unsanitized redirect_to URL ($_REQUEST['redirect_to']).
 288   * @param WP_User $user            The WP_User object corresponding to a successfully
 289   *                                 logged-in user. Otherwise a WP_Error object.
 290   * @return string The redirect URL.
 291   */
 292  function bp_core_login_redirect( $redirect_to, $redirect_to_raw, $user ) {
 293  
 294      // Only modify the redirect if we're on the main BP blog.
 295      if ( !bp_is_root_blog() ) {
 296          return $redirect_to;
 297      }
 298  
 299      // Only modify the redirect once the user is logged in.
 300      if ( !is_a( $user, 'WP_User' ) ) {
 301          return $redirect_to;
 302      }
 303  
 304      /**
 305       * Filters whether or not to redirect.
 306       *
 307       * Allows plugins to have finer grained control of redirect upon login.
 308       *
 309       * @since 1.6.0
 310       *
 311       * @param bool    $value           Whether or not to redirect.
 312       * @param string  $redirect_to     Sanitized URL to be redirected to.
 313       * @param string  $redirect_to_raw Unsanitized URL to be redirected to.
 314       * @param WP_User $user            The WP_User object corresponding to a
 315       *                                 successfully logged in user.
 316       */
 317      $maybe_redirect = apply_filters( 'bp_core_login_redirect', false, $redirect_to, $redirect_to_raw, $user );
 318      if ( false !== $maybe_redirect ) {
 319          return $maybe_redirect;
 320      }
 321  
 322      // If a 'redirect_to' parameter has been passed that contains 'wp-admin', verify that the
 323      // logged-in user has any business to conduct in the Dashboard before allowing the
 324      // redirect to go through.
 325      if ( !empty( $redirect_to ) && ( false === strpos( $redirect_to, 'wp-admin' ) || user_can( $user, 'edit_posts' ) ) ) {
 326          return $redirect_to;
 327      }
 328  
 329      if ( false === strpos( wp_get_referer(), 'wp-login.php' ) && false === strpos( wp_get_referer(), 'activate' ) && empty( $_REQUEST['nr'] ) ) {
 330          return wp_get_referer();
 331      }
 332  
 333      /**
 334       * Filters the URL to redirect users to upon successful login.
 335       *
 336       * @since 1.9.0
 337       *
 338       * @param string $value URL to redirect to.
 339       */
 340      return apply_filters( 'bp_core_login_redirect_to', bp_get_root_domain() );
 341  }
 342  add_filter( 'bp_login_redirect', 'bp_core_login_redirect', 10, 3 );
 343  
 344  /**
 345   * Decode HTML entities for plain-text emails.
 346   *
 347   * @since 2.5.0
 348   *
 349   * @param string $retval    Current email content.
 350   * @param string $prop      Email property to check against.
 351   * @param string $transform Either 'raw' or 'replace-tokens'.
 352   * @return string|null $retval Modified email content.
 353   */
 354  function bp_email_plaintext_entity_decode( $retval, $prop, $transform ) {
 355      switch ( $prop ) {
 356          case 'content_plaintext' :
 357          case 'subject' :
 358              // Only decode if 'replace-tokens' is the current type.
 359              if ( 'replace-tokens' === $transform ) {
 360                  return html_entity_decode( $retval, ENT_QUOTES );
 361              } else {
 362                  return $retval;
 363              }
 364              break;
 365  
 366          default :
 367              return $retval;
 368              break;
 369      }
 370  }
 371  add_filter( 'bp_email_get_property', 'bp_email_plaintext_entity_decode', 10, 3 );
 372  
 373  /**
 374   * Replace the generated password in the welcome email with '[User Set]'.
 375   *
 376   * On a standard BP installation, users who register themselves also set their
 377   * own passwords. Therefore there is no need for the insecure practice of
 378   * emailing the plaintext password to the user in the welcome email.
 379   *
 380   * This filter will not fire when a user is registered by the site admin.
 381   *
 382   * @since 1.2.1
 383   *
 384   * @param string $welcome_email Complete email passed through WordPress.
 385   * @return string Filtered $welcome_email with the password replaced
 386   *                by '[User Set]'.
 387   */
 388  function bp_core_filter_user_welcome_email( $welcome_email ) {
 389  
 390      // Don't touch the email when a user is registered by the site admin.
 391      if ( ( is_admin() || is_network_admin() ) && buddypress()->members->admin->signups_page != get_current_screen()->id ) {
 392          return $welcome_email;
 393      }
 394  
 395      if ( strpos( bp_get_requested_url(), 'wp-activate.php' ) !== false ) {
 396          return $welcome_email;
 397      }
 398  
 399      // Don't touch the email if we don't have a custom registration template.
 400      if ( ! bp_has_custom_signup_page() ) {
 401          return $welcome_email;
 402      }
 403  
 404      // [User Set] Replaces 'PASSWORD' in welcome email; Represents value set by user
 405      return str_replace( 'PASSWORD', __( '[User Set]', 'buddypress' ), $welcome_email );
 406  }
 407  add_filter( 'update_welcome_user_email', 'bp_core_filter_user_welcome_email' );
 408  
 409  /**
 410   * Replace the generated password in the welcome email with '[User Set]'.
 411   *
 412   * On a standard BP installation, users who register themselves also set their
 413   * own passwords. Therefore there is no need for the insecure practice of
 414   * emailing the plaintext password to the user in the welcome email.
 415   *
 416   * This filter will not fire when a user is registered by the site admin.
 417   *
 418   * @since 1.2.1
 419   *
 420   * @param string $welcome_email Complete email passed through WordPress.
 421   * @param int    $blog_id       ID of the blog user is joining.
 422   * @param int    $user_id       ID of the user joining.
 423   * @param string $password      Password of user.
 424   * @return string Filtered $welcome_email with $password replaced by '[User Set]'.
 425   */
 426  function bp_core_filter_blog_welcome_email( $welcome_email, $blog_id, $user_id, $password ) {
 427  
 428      // Don't touch the email when a user is registered by the site admin.
 429      if ( ( is_admin() || is_network_admin() ) && buddypress()->members->admin->signups_page != get_current_screen()->id ) {
 430          return $welcome_email;
 431      }
 432  
 433      // Don't touch the email if we don't have a custom registration template.
 434      if ( ! bp_has_custom_signup_page() )
 435          return $welcome_email;
 436  
 437      // [User Set] Replaces $password in welcome email; Represents value set by user
 438      return str_replace( $password, __( '[User Set]', 'buddypress' ), $welcome_email );
 439  }
 440  add_filter( 'update_welcome_email', 'bp_core_filter_blog_welcome_email', 10, 4 );
 441  
 442  /**
 443   * Notify new users of a successful registration (with blog).
 444   *
 445   * This function filter's WP's 'wpmu_signup_blog_notification', and replaces
 446   * WP's default welcome email with a BuddyPress-specific message.
 447   *
 448   * @since 1.0.0
 449   *
 450   * @see wpmu_signup_blog_notification() for a description of parameters.
 451   *
 452   * @param string $domain     The new blog domain.
 453   * @param string $path       The new blog path.
 454   * @param string $title      The site title.
 455   * @param string $user       The user's login name.
 456   * @param string $user_email The user's email address.
 457   * @param string $key        The activation key created in wpmu_signup_blog().
 458   * @return bool              Returns false to stop original WPMU function from continuing.
 459   */
 460  function bp_core_activation_signup_blog_notification( $domain, $path, $title, $user, $user_email, $key ) {
 461      $args = array(
 462          'tokens' => array(
 463              'activate-site.url' => esc_url( bp_get_activation_page() . '?key=' . urlencode( $key ) ),
 464              'domain'            => $domain,
 465              'key_blog'          => $key,
 466              'path'              => $path,
 467              'user-site.url'     => esc_url( set_url_scheme( "http://{$domain}{$path}" ) ),
 468              'title'             => $title,
 469              'user.email'        => $user_email,
 470          ),
 471      );
 472  
 473      $signups = BP_Signup::get(
 474          array(
 475              'user_login' => $user,
 476          )
 477      );
 478  
 479      $salutation = $user;
 480      if ( $signups ) {
 481          $signup = $signups['signups'][0];
 482          if ( isset( $signup->meta[ 'field_' . bp_xprofile_fullname_field_id() ] ) ) {
 483              $salutation = $signup->meta[ 'field_' . bp_xprofile_fullname_field_id() ];
 484          }
 485      }
 486  
 487      bp_send_email( 'core-user-registration-with-blog', array( array( $user_email => $salutation ) ), $args );
 488  
 489      // Return false to stop the original WPMU function from continuing.
 490      return false;
 491  }
 492  add_filter( 'wpmu_signup_blog_notification', 'bp_core_activation_signup_blog_notification', 1, 6 );
 493  
 494  /**
 495   * Notify new users of a successful registration (without blog).
 496   *
 497   * @since 1.0.0
 498   *
 499   * @see wpmu_signup_user_notification() for a full description of params.
 500   *
 501   * @param string $user       The user's login name.
 502   * @param string $user_email The user's email address.
 503   * @param string $key        The activation key created in wpmu_signup_user().
 504   * @param array  $meta       By default, an empty array.
 505   * @return false|string Returns false to stop original WPMU function from continuing.
 506   */
 507  function bp_core_activation_signup_user_notification( $user, $user_email, $key, $meta ) {
 508      if ( is_admin() ) {
 509  
 510          // If the user is created from the WordPress Add User screen, don't send BuddyPress signup notifications.
 511          if( in_array( get_current_screen()->id, array( 'user', 'user-network' ) ) ) {
 512              // If the Super Admin want to skip confirmation email.
 513              if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) {
 514                  return false;
 515  
 516              // WordPress will manage the signup process.
 517              } else {
 518                  return $user;
 519              }
 520  
 521          /*
 522           * There can be a case where the user was created without the skip confirmation
 523           * And the super admin goes in pending accounts to resend it. In this case, as the
 524           * meta['password'] is not set, the activation url must be WordPress one.
 525           */
 526          } elseif ( buddypress()->members->admin->signups_page == get_current_screen()->id ) {
 527              $is_hashpass_in_meta = maybe_unserialize( $meta );
 528  
 529              if ( empty( $is_hashpass_in_meta['password'] ) ) {
 530                  return $user;
 531              }
 532          }
 533      }
 534  
 535      $user_id = 0;
 536      $user_object = get_user_by( 'login', $user );
 537      if ( $user_object ) {
 538          $user_id = $user_object->ID;
 539      }
 540  
 541      $salutation = $user;
 542      if ( isset( $meta[ 'field_' . bp_xprofile_fullname_field_id() ] ) ) {
 543          $salutation = $meta[ 'field_' . bp_xprofile_fullname_field_id() ];
 544      } elseif ( $user_id ) {
 545          $salutation = bp_core_get_user_displayname( $user_id );
 546      }
 547  
 548      $args = array(
 549          'tokens' => array(
 550              'activate.url' => esc_url( trailingslashit( bp_get_activation_page() ) . "{$key}/" ),
 551              'key'          => $key,
 552              'user.email'   => $user_email,
 553              'user.id'      => $user_id,
 554          ),
 555      );
 556      bp_send_email( 'core-user-registration', array( array( $user_email => $salutation ) ), $args );
 557  
 558      // Return false to stop the original WPMU function from continuing.
 559      return false;
 560  }
 561  add_filter( 'wpmu_signup_user_notification', 'bp_core_activation_signup_user_notification', 1, 4 );
 562  
 563  /**
 564   * Filter the page title for BuddyPress pages.
 565   *
 566   * @since 1.5.0
 567   *
 568   * @see wp_title()
 569   * @global object $bp BuddyPress global settings.
 570   *
 571   * @param string $title       Original page title.
 572   * @param string $sep         How to separate the various items within the page title.
 573   * @param string $seplocation Direction to display title.
 574   * @return string              New page title.
 575   */
 576  function bp_modify_page_title( $title = '', $sep = '&raquo;', $seplocation = 'right' ) {
 577      global $paged, $page, $_wp_theme_features;
 578  
 579      // Get the BuddyPress title parts.
 580      $bp_title_parts = bp_get_title_parts( $seplocation );
 581  
 582      // If not set, simply return the original title.
 583      if ( ! $bp_title_parts ) {
 584          return $title;
 585      }
 586  
 587      // Get the blog name, so we can check if the original $title included it.
 588      $blogname = get_bloginfo( 'name', 'display' );
 589  
 590      /**
 591       * Are we going to fake 'title-tag' theme functionality?
 592       *
 593       * @link https://buddypress.trac.wordpress.org/ticket/6107
 594       * @see wp_title()
 595       */
 596      $title_tag_compatibility = (bool) ( ! empty( $_wp_theme_features['title-tag'] ) || ( $blogname && strstr( $title, $blogname ) ) );
 597  
 598      // Append the site title to title parts if theme supports title tag.
 599      if ( true === $title_tag_compatibility ) {
 600          $bp_title_parts['site'] = $blogname;
 601  
 602          if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() && ! bp_is_single_activity() ) {
 603              $bp_title_parts['page'] = sprintf( __( 'Page %s', 'buddypress' ), max( $paged, $page ) );
 604          }
 605      }
 606  
 607      // Pad the separator with 1 space on each side.
 608      $prefix = str_pad( $sep, strlen( $sep ) + 2, ' ', STR_PAD_BOTH );
 609  
 610      // Join the parts together.
 611      $new_title = join( $prefix, array_filter( $bp_title_parts ) );
 612  
 613      // Append the prefix for pre `title-tag` compatibility.
 614      if ( false === $title_tag_compatibility ) {
 615          $new_title = $new_title . $prefix;
 616      }
 617  
 618      /**
 619       * Filters the older 'wp_title' page title for BuddyPress pages.
 620       *
 621       * @since 1.5.0
 622       *
 623       * @param string $new_title   The BuddyPress page title.
 624       * @param string $title       The original WordPress page title.
 625       * @param string $sep         The title parts separator.
 626       * @param string $seplocation Location of the separator (left or right).
 627       */
 628      return apply_filters( 'bp_modify_page_title', $new_title, $title, $sep, $seplocation );
 629  }
 630  add_filter( 'wp_title',             'bp_modify_page_title', 20, 3 );
 631  add_filter( 'bp_modify_page_title', 'wptexturize'                 );
 632  add_filter( 'bp_modify_page_title', 'convert_chars'               );
 633  add_filter( 'bp_modify_page_title', 'esc_html'                    );
 634  
 635  /**
 636   * Filter the document title for BuddyPress pages.
 637   *
 638   * @since 2.4.3
 639   *
 640   * @param array $title The WordPress document title parts.
 641   * @return array the unchanged title parts or the BuddyPress ones
 642   */
 643  function bp_modify_document_title_parts( $title = array() ) {
 644      // Get the BuddyPress title parts.
 645      $bp_title_parts = bp_get_title_parts();
 646  
 647      // If not set, simply return the original title.
 648      if ( ! $bp_title_parts ) {
 649          return $title;
 650      }
 651  
 652      // Get the separator used by wp_get_document_title().
 653      $sep = apply_filters( 'document_title_separator', '-' );
 654  
 655      // Build the BuddyPress portion of the title.
 656      // We don't need to sanitize this as WordPress will take care of it.
 657      $bp_title = array(
 658          'title' => join( " $sep ", $bp_title_parts )
 659      );
 660  
 661      // Add the pagination number if needed (not sure if this is necessary).
 662      if ( isset( $title['page'] ) && ! bp_is_single_activity() ) {
 663          $bp_title['page'] = $title['page'];
 664      }
 665  
 666      // Add the sitename if needed.
 667      if ( isset( $title['site'] ) ) {
 668          $bp_title['site'] = $title['site'];
 669      }
 670  
 671      /**
 672       * Filters BuddyPress title parts that will be used into the document title.
 673       *
 674       * @since 2.4.3
 675       *
 676       * @param array $bp_title The BuddyPress page title parts.
 677       * @param array $title    The original WordPress title parts.
 678       */
 679      return apply_filters( 'bp_modify_document_title_parts', $bp_title, $title );
 680  }
 681  add_filter( 'document_title_parts', 'bp_modify_document_title_parts', 20, 1 );
 682  
 683  /**
 684   * Add BuddyPress-specific items to the wp_nav_menu.
 685   *
 686   * @since 1.9.0
 687   *
 688   * @param WP_Post $menu_item The menu item.
 689   * @return WP_Post The modified WP_Post object.
 690   */
 691  function bp_setup_nav_menu_item( $menu_item ) {
 692      if ( is_admin() ) {
 693          return $menu_item;
 694      }
 695  
 696      // Prevent a notice error when using the customizer.
 697      $menu_classes = $menu_item->classes;
 698  
 699      if ( is_array( $menu_classes ) ) {
 700          $menu_classes = implode( ' ', $menu_item->classes);
 701      }
 702  
 703      // We use information stored in the CSS class to determine what kind of
 704      // menu item this is, and how it should be treated.
 705      preg_match( '/\sbp-(.*)-nav/', $menu_classes, $matches );
 706  
 707      // If this isn't a BP menu item, we can stop here.
 708      if ( empty( $matches[1] ) ) {
 709          return $menu_item;
 710      }
 711  
 712      switch ( $matches[1] ) {
 713          case 'login' :
 714              if ( is_user_logged_in() ) {
 715                  $menu_item->_invalid = true;
 716              } else {
 717                  $menu_item->url = wp_login_url( bp_get_requested_url() );
 718              }
 719  
 720              break;
 721  
 722          case 'logout' :
 723              if ( ! is_user_logged_in() ) {
 724                  $menu_item->_invalid = true;
 725              } else {
 726                  $menu_item->url = wp_logout_url( bp_get_requested_url() );
 727              }
 728  
 729              break;
 730  
 731          // Don't show the Register link to logged-in users.
 732          case 'register' :
 733              if ( is_user_logged_in() ) {
 734                  $menu_item->_invalid = true;
 735              }
 736  
 737              break;
 738  
 739          // All other BP nav items are specific to the logged-in user,
 740          // and so are not relevant to logged-out users.
 741          default:
 742              if ( is_user_logged_in() ) {
 743                  $menu_item->url = bp_nav_menu_get_item_url( $matches[1] );
 744              } else {
 745                  $menu_item->_invalid = true;
 746              }
 747  
 748              break;
 749      }
 750  
 751      // If component is deactivated, make sure menu item doesn't render.
 752      if ( empty( $menu_item->url ) ) {
 753          $menu_item->_invalid = true;
 754  
 755      // Highlight the current page.
 756      } else {
 757          $current = bp_get_requested_url();
 758          if ( strpos( $current, $menu_item->url ) !== false ) {
 759              if ( is_array( $menu_item->classes ) ) {
 760                  $menu_item->classes[] = 'current_page_item';
 761                  $menu_item->classes[] = 'current-menu-item';
 762              } else {
 763                  $menu_item->classes = array( 'current_page_item', 'current-menu-item' );
 764              }
 765          }
 766      }
 767  
 768      return $menu_item;
 769  }
 770  add_filter( 'wp_setup_nav_menu_item', 'bp_setup_nav_menu_item', 10, 1 );
 771  
 772  /**
 773   * Populate BuddyPress user nav items for the customizer.
 774   *
 775   * @since 2.3.3
 776   *
 777   * @param array   $items  The array of menu items.
 778   * @param string  $type   The requested type.
 779   * @param string  $object The requested object name.
 780   * @param integer $page   The page num being requested.
 781   * @return array The paginated BuddyPress user nav items.
 782   */
 783  function bp_customizer_nav_menus_get_items( $items = array(), $type = '', $object = '', $page = 0 ) {
 784      if ( 'bp_loggedin_nav' === $object ) {
 785          $bp_items = bp_nav_menu_get_loggedin_pages();
 786      } elseif ( 'bp_loggedout_nav' === $object ) {
 787          $bp_items = bp_nav_menu_get_loggedout_pages();
 788      } else {
 789          return $items;
 790      }
 791  
 792      foreach ( $bp_items as $bp_item ) {
 793          $items[] = array(
 794              'id'         => "bp-{$bp_item->post_excerpt}",
 795              'title'      => html_entity_decode( $bp_item->post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ),
 796              'type'       => $type,
 797              'url'        => esc_url_raw( $bp_item->guid ),
 798              'classes'    => "bp-menu bp-{$bp_item->post_excerpt}-nav",
 799              'type_label' => _x( 'Custom Link', 'customizer menu type label', 'buddypress' ),
 800              'object'     => $object,
 801              'object_id'  => -1,
 802          );
 803      }
 804  
 805      return array_slice( $items, 10 * $page, 10 );
 806  }
 807  add_filter( 'customize_nav_menu_available_items', 'bp_customizer_nav_menus_get_items', 10, 4 );
 808  
 809  /**
 810   * Set BuddyPress item navs for the customizer.
 811   *
 812   * @since 2.3.3
 813   *
 814   * @param array $item_types An associative array structured for the customizer.
 815   * @return array $item_types An associative array structured for the customizer.
 816   */
 817  function bp_customizer_nav_menus_set_item_types( $item_types = array() ) {
 818      $item_types = array_merge( $item_types, array(
 819          'bp_loggedin_nav' => array(
 820              'title'  => _x( 'BuddyPress (logged-in)', 'customizer menu section title', 'buddypress' ),
 821              'type'   => 'bp_nav',
 822              'object' => 'bp_loggedin_nav',
 823          ),
 824          'bp_loggedout_nav' => array(
 825              'title'  => _x( 'BuddyPress (logged-out)', 'customizer menu section title', 'buddypress' ),
 826              'type'   => 'bp_nav',
 827              'object' => 'bp_loggedout_nav',
 828          ),
 829      ) );
 830  
 831      return $item_types;
 832  }
 833  add_filter( 'customize_nav_menu_available_item_types', 'bp_customizer_nav_menus_set_item_types', 10, 1 );
 834  
 835  /**
 836   * Filter SQL query strings to swap out the 'meta_id' column.
 837   *
 838   * WordPress uses the meta_id column for commentmeta and postmeta, and so
 839   * hardcodes the column name into its *_metadata() functions. BuddyPress, on
 840   * the other hand, uses 'id' for the primary column. To make WP's functions
 841   * usable for BuddyPress, we use this just-in-time filter on 'query' to swap
 842   * 'meta_id' with 'id.
 843   *
 844   * @since 2.0.0
 845   *
 846   * @access private Do not use.
 847   *
 848   * @param string $q SQL query.
 849   * @return string
 850   */
 851  function bp_filter_metaid_column_name( $q ) {
 852      /*
 853       * Replace quoted content with __QUOTE__ to avoid false positives.
 854       * This regular expression will match nested quotes.
 855       */
 856      $quoted_regex = "/'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'/s";
 857      preg_match_all( $quoted_regex, $q, $quoted_matches );
 858      $q = preg_replace( $quoted_regex, '__QUOTE__', $q );
 859  
 860      $q = str_replace( 'meta_id', 'id', $q );
 861  
 862      // Put quoted content back into the string.
 863      if ( ! empty( $quoted_matches[0] ) ) {
 864          for ( $i = 0; $i < count( $quoted_matches[0] ); $i++ ) {
 865              $quote_pos = strpos( $q, '__QUOTE__' );
 866              $q = substr_replace( $q, $quoted_matches[0][ $i ], $quote_pos, 9 );
 867          }
 868      }
 869  
 870      return $q;
 871  }
 872  
 873  /**
 874   * Filter the edit post link to avoid its display in BuddyPress pages.
 875   *
 876   * @since 2.1.0
 877   *
 878   * @param string $edit_link The edit link.
 879   * @param int    $post_id   Post ID.
 880   * @return false|string Will be a boolean (false) if $post_id is 0. Will be a string (the unchanged edit link)
 881   *                      otherwise
 882   */
 883  function bp_core_filter_edit_post_link( $edit_link = '', $post_id = 0 ) {
 884      if ( 0 === $post_id ) {
 885          $edit_link = false;
 886      }
 887  
 888      return $edit_link;
 889  }
 890  
 891  /**
 892   * Should BuddyPress load the mentions scripts and related assets, including results to prime the
 893   * mentions suggestions?
 894   *
 895   * @since 2.2.0
 896   *
 897   * @param bool $load_mentions    True to load mentions assets, false otherwise.
 898   * @param bool $mentions_enabled True if mentions are enabled.
 899   * @return bool True if mentions scripts should be loaded.
 900   */
 901  function bp_maybe_load_mentions_scripts_for_blog_content( $load_mentions, $mentions_enabled ) {
 902      if ( ! $mentions_enabled ) {
 903          return $load_mentions;
 904      }
 905  
 906      if ( $load_mentions || ( bp_is_blog_page() && is_singular() && comments_open() ) ) {
 907          return true;
 908      }
 909  
 910      return $load_mentions;
 911  }
 912  add_filter( 'bp_activity_maybe_load_mentions_scripts', 'bp_maybe_load_mentions_scripts_for_blog_content', 10, 2 );
 913  
 914  /**
 915   * Injects specific BuddyPress CSS classes into a widget sidebar.
 916   *
 917   * Helps to standardize styling of BuddyPress widgets within a theme that
 918   * does not use dynamic CSS classes in their widget sidebar's 'before_widget'
 919   * call.
 920   *
 921   * @since 2.4.0
 922   * @access private
 923   *
 924   * @global array $wp_registered_widgets Current registered widgets.
 925   *
 926   * @param array $params Current sidebar params.
 927   * @return array
 928   */
 929  function _bp_core_inject_bp_widget_css_class( $params ) {
 930      global $wp_registered_widgets;
 931  
 932      $widget_id = $params[0]['widget_id'];
 933  
 934      // If callback isn't an array, bail.
 935      if ( false === is_array( $wp_registered_widgets[ $widget_id ]['callback'] ) ) {
 936          return $params;
 937      }
 938  
 939      // If the current widget isn't a BuddyPress one, stop!
 940      // We determine if a widget is a BuddyPress widget, if the widget class
 941      // begins with 'bp_'.
 942      if ( 0 !== strpos( $wp_registered_widgets[ $widget_id ]['callback'][0]->id_base, 'bp_' ) ) {
 943          return $params;
 944      }
 945  
 946      // Dynamically add our widget CSS classes for BP widgets if not already there.
 947      $classes = array();
 948  
 949      // Try to find 'widget' CSS class.
 950      if ( false === strpos( $params[0]['before_widget'], 'widget ' ) ) {
 951          $classes[] = 'widget';
 952      }
 953  
 954      // Try to find 'buddypress' CSS class.
 955      if ( false === strpos( $params[0]['before_widget'], ' buddypress' ) ) {
 956          $classes[] = 'buddypress';
 957      }
 958  
 959      // Stop if widget already has our CSS classes.
 960      if ( empty( $classes ) ) {
 961          return $params;
 962      }
 963  
 964      // CSS injection time!
 965      $params[0]['before_widget'] = str_replace( 'class="', 'class="' . implode( ' ', $classes ) . ' ', $params[0]['before_widget'] );
 966  
 967      return $params;
 968  }
 969  add_filter( 'dynamic_sidebar_params', '_bp_core_inject_bp_widget_css_class' );
 970  
 971  /**
 972   * Add email link styles to rendered email template.
 973   *
 974   * This is only used when the email content has been merged into the email template.
 975   *
 976   * @since 2.5.0
 977   *
 978   * @param string $value         Property value.
 979   * @param string $property_name Email template property name.
 980   * @param string $transform     How the return value was transformed.
 981   * @return string Updated value.
 982   */
 983  function bp_email_add_link_color_to_template( $value, $property_name, $transform ) {
 984      if ( $property_name !== 'template' || $transform !== 'add-content' ) {
 985          return $value;
 986      }
 987  
 988      $settings    = bp_email_get_appearance_settings();
 989      $replacement = 'style="color: ' . esc_attr( $settings['link_text_color'] ) . ';';
 990  
 991      // Find all links.
 992      preg_match_all( '#<a[^>]+>#i', $value, $links, PREG_SET_ORDER );
 993      foreach ( $links as $link ) {
 994          $new_link = $link = array_shift( $link );
 995  
 996          // Add/modify style property.
 997          if ( strpos( $link, 'style="' ) !== false ) {
 998              $new_link = str_replace( 'style="', $replacement, $link );
 999          } else {
1000              $new_link = str_replace( '<a ', "<a {$replacement}\" ", $link );
1001          }
1002  
1003          if ( $new_link !== $link ) {
1004              $value = str_replace( $link, $new_link, $value );
1005          }
1006      }
1007  
1008      return $value;
1009  }
1010  add_filter( 'bp_email_get_property', 'bp_email_add_link_color_to_template', 6, 3 );
1011  
1012  /**
1013   * Add custom headers to outgoing emails.
1014   *
1015   * @since 2.5.0
1016   *
1017   * @param array    $headers   Array of email headers.
1018   * @param string   $property  Name of property. Unused.
1019   * @param string   $transform Return value transformation. Unused.
1020   * @param BP_Email $email     Email object reference.
1021   * @return array
1022   */
1023  function bp_email_set_default_headers( $headers, $property, $transform, $email ) {
1024      $headers['X-BuddyPress']      = bp_get_version();
1025      $headers['X-BuddyPress-Type'] = $email->get( 'type' );
1026  
1027      $tokens = $email->get_tokens();
1028  
1029      // Add 'List-Unsubscribe' header if applicable.
1030      if ( ! empty( $tokens['unsubscribe'] ) && $tokens['unsubscribe'] !== wp_login_url() ) {
1031          $user = get_user_by( 'email', $tokens['recipient.email'] );
1032  
1033          $link = bp_email_get_unsubscribe_link( array(
1034              'user_id'           => $user->ID,
1035              'notification_type' => $email->get( 'type' ),
1036          ) );
1037  
1038          if ( ! empty( $link ) ) {
1039              $headers['List-Unsubscribe'] = sprintf( '<%s>', esc_url_raw( $link ) );
1040          }
1041      }
1042  
1043      return $headers;
1044  }
1045  add_filter( 'bp_email_get_headers', 'bp_email_set_default_headers', 6, 4 );
1046  
1047  /**
1048   * Add default email tokens.
1049   *
1050   * @since 2.5.0
1051   *
1052   * @param array    $tokens        Email tokens.
1053   * @param string   $property_name Unused.
1054   * @param string   $transform     Unused.
1055   * @param BP_Email $email         Email being sent.
1056   * @return array
1057   */
1058  function bp_email_set_default_tokens( $tokens, $property_name, $transform, $email ) {
1059      $tokens['site.admin-email'] = bp_get_option( 'admin_email' );
1060      $tokens['site.url']         = bp_get_root_domain();
1061      $tokens['email.subject']    = $email->get_subject();
1062  
1063      // These options are escaped with esc_html on the way into the database in sanitize_option().
1064      $tokens['site.description'] = wp_specialchars_decode( bp_get_option( 'blogdescription' ), ENT_QUOTES );
1065      $tokens['site.name']        = wp_specialchars_decode( bp_get_option( 'blogname' ), ENT_QUOTES );
1066  
1067      // Default values for tokens set conditionally below.
1068      $tokens['email.preheader']     = '';
1069      $tokens['recipient.email']     = '';
1070      $tokens['recipient.name']      = '';
1071      $tokens['recipient.username']  = '';
1072  
1073      // Who is the email going to?
1074      $recipient = $email->get( 'to' );
1075      if ( $recipient ) {
1076          $recipient = array_shift( $recipient );
1077          $user_obj  = $recipient->get_user( 'search-email' );
1078  
1079          $tokens['recipient.email'] = $recipient->get_address();
1080          $tokens['recipient.name']  = $recipient->get_name();
1081  
1082          if ( ! $user_obj && $tokens['recipient.email'] ) {
1083              $user_obj = get_user_by( 'email', $tokens['recipient.email'] );
1084          }
1085  
1086          if ( $user_obj ) {
1087              $tokens['recipient.username'] = $user_obj->user_login;
1088  
1089              if ( bp_is_active( 'settings' ) && empty( $tokens['unsubscribe'] ) ) {
1090                  $tokens['unsubscribe'] = esc_url( sprintf(
1091                      '%s%s/notifications/',
1092                      bp_core_get_user_domain( $user_obj->ID ),
1093                      bp_get_settings_slug()
1094                  ) );
1095              }
1096          }
1097      }
1098  
1099      // Set default unsubscribe link if not passed.
1100      if ( empty( $tokens['unsubscribe'] ) ) {
1101          $tokens['unsubscribe'] = wp_login_url();
1102      }
1103  
1104      // Email preheader.
1105      $preheader = $email->get_preheader();
1106      if ( $preheader ) {
1107          $tokens['email.preheader'] = $preheader;
1108      }
1109  
1110      return $tokens;
1111  }
1112  add_filter( 'bp_email_get_tokens', 'bp_email_set_default_tokens', 6, 4 );
1113  
1114  /**
1115   * Find and render the template for Email posts (the Customizer and admin previews).
1116   *
1117   * Misuses the `template_include` filter which expects a string, but as we need to replace
1118   * the `{{{content}}}` token with the post's content, we use object buffering to load the
1119   * template, replace the token, and render it.
1120   *
1121   * The function returns an empty string to prevent WordPress rendering another template.
1122   *
1123   * @since 2.5.0
1124   *
1125   * @param string $template Path to template (probably single.php).
1126   * @return string
1127   */
1128  function bp_core_render_email_template( $template ) {
1129      if ( get_post_type() !== bp_get_email_post_type() || ! is_single() ) {
1130          return $template;
1131      }
1132  
1133      /**
1134       * Filter template used to display Email posts.
1135       *
1136       * @since 2.5.0
1137       *
1138       * @param string $template Path to current template (probably single.php).
1139       */
1140      $email_template = apply_filters( 'bp_core_render_email_template',
1141          bp_locate_template( bp_email_get_template( get_queried_object() ), false ),
1142          $template
1143      );
1144  
1145      if ( ! $email_template ) {
1146          return $template;
1147      }
1148  
1149      ob_start();
1150      include( $email_template );
1151      $template = ob_get_contents();
1152      ob_end_clean();
1153  
1154      // Make sure we add a <title> tag so WP Customizer picks it up.
1155      $template = str_replace( '<head>', '<head><title>' . esc_html_x( 'BuddyPress Emails', 'screen heading', 'buddypress' ) . '</title>', $template );
1156      echo str_replace( '{{{content}}}', wpautop( get_post()->post_content ), $template );
1157  
1158      /*
1159       * Link colours are applied directly in the email template before sending, so we
1160       * need to add an extra style here to set the colour for the Customizer or preview.
1161       */
1162      $settings = bp_email_get_appearance_settings();
1163      printf(
1164          '<style>a { color: %s; }</style>',
1165          esc_attr( $settings['highlight_color'] )
1166      );
1167  
1168      return '';
1169  }
1170  add_action( 'bp_template_include', 'bp_core_render_email_template', 12 );


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