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


Generated: Thu Nov 21 01:00:57 2024 Cross-referenced by PHPXref 0.7.1