[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
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 $args = array( 465 'tokens' => array( 466 'activate-site.url' => esc_url( bp_get_activation_page() . '?key=' . urlencode( $key ) ), 467 'domain' => $domain, 468 'key_blog' => $key, 469 'path' => $path, 470 'user-site.url' => esc_url( set_url_scheme( "http://{$domain}{$path}" ) ), 471 'title' => $title, 472 'user.email' => $user_email, 473 ), 474 ); 475 476 $signups = BP_Signup::get( 477 array( 478 'user_login' => $user, 479 ) 480 ); 481 482 $salutation = $user; 483 if ( $signups && bp_is_active( 'xprofile' ) ) { 484 $signup = $signups['signups'][0]; 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 bp_send_email( 'core-user-registration-with-blog', array( array( $user_email => $salutation ) ), $args ); 491 492 // Return false to stop the original WPMU function from continuing. 493 return false; 494 } 495 add_filter( 'wpmu_signup_blog_notification', 'bp_core_activation_signup_blog_notification', 1, 6 ); 496 497 /** 498 * Notify new users of a successful registration (without blog). 499 * 500 * @since 1.0.0 501 * 502 * @see wpmu_signup_user_notification() for a full description of params. 503 * 504 * @param string $user The user's login name. 505 * @param string $user_email The user's email address. 506 * @param string $key The activation key created in wpmu_signup_user(). 507 * @param array $meta By default, an empty array. 508 * @return false|string Returns false to stop original WPMU function from continuing. 509 */ 510 function bp_core_activation_signup_user_notification( $user, $user_email, $key, $meta ) { 511 if ( is_admin() ) { 512 513 // If the user is created from the WordPress Add User screen, don't send BuddyPress signup notifications. 514 if( in_array( get_current_screen()->id, array( 'user', 'user-network' ) ) ) { 515 // If the Super Admin want to skip confirmation email. 516 if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) { 517 return false; 518 519 // WordPress will manage the signup process. 520 } else { 521 return $user; 522 } 523 524 /* 525 * There can be a case where the user was created without the skip confirmation 526 * And the super admin goes in pending accounts to resend it. In this case, as the 527 * meta['password'] is not set, the activation url must be WordPress one. 528 */ 529 } elseif ( buddypress()->members->admin->signups_page == get_current_screen()->id ) { 530 $is_hashpass_in_meta = maybe_unserialize( $meta ); 531 532 if ( empty( $is_hashpass_in_meta['password'] ) ) { 533 return $user; 534 } 535 } 536 } 537 538 $user_id = 0; 539 $user_object = get_user_by( 'login', $user ); 540 if ( $user_object ) { 541 $user_id = $user_object->ID; 542 } 543 544 $salutation = $user; 545 if ( bp_is_active( 'xprofile' ) && isset( $meta[ 'field_' . bp_xprofile_fullname_field_id() ] ) ) { 546 $salutation = $meta[ 'field_' . bp_xprofile_fullname_field_id() ]; 547 } elseif ( $user_id ) { 548 $salutation = bp_core_get_user_displayname( $user_id ); 549 } 550 551 $args = array( 552 'tokens' => array( 553 'activate.url' => esc_url( trailingslashit( bp_get_activation_page() ) . "{$key}/" ), 554 'key' => $key, 555 'user.email' => $user_email, 556 'user.id' => $user_id, 557 ), 558 ); 559 bp_send_email( 'core-user-registration', array( array( $user_email => $salutation ) ), $args ); 560 561 // Return false to stop the original WPMU function from continuing. 562 return false; 563 } 564 add_filter( 'wpmu_signup_user_notification', 'bp_core_activation_signup_user_notification', 1, 4 ); 565 566 /** 567 * Filter the page title for BuddyPress pages. 568 * 569 * @since 1.5.0 570 * 571 * @see wp_title() 572 * @global object $bp BuddyPress global settings. 573 * 574 * @param string $title Original page title. 575 * @param string $sep How to separate the various items within the page title. 576 * @param string $seplocation Direction to display title. 577 * @return string New page title. 578 */ 579 function bp_modify_page_title( $title = '', $sep = '»', $seplocation = 'right' ) { 580 global $paged, $page, $_wp_theme_features; 581 582 // Get the BuddyPress title parts. 583 $bp_title_parts = bp_get_title_parts( $seplocation ); 584 585 // If not set, simply return the original title. 586 if ( ! $bp_title_parts ) { 587 return $title; 588 } 589 590 // Get the blog name, so we can check if the original $title included it. 591 $blogname = get_bloginfo( 'name', 'display' ); 592 593 /** 594 * Are we going to fake 'title-tag' theme functionality? 595 * 596 * @link https://buddypress.trac.wordpress.org/ticket/6107 597 * @see wp_title() 598 */ 599 $title_tag_compatibility = (bool) ( ! empty( $_wp_theme_features['title-tag'] ) || ( $blogname && strstr( $title, $blogname ) ) ); 600 601 // Append the site title to title parts if theme supports title tag. 602 if ( true === $title_tag_compatibility ) { 603 $bp_title_parts['site'] = $blogname; 604 605 if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() && ! bp_is_single_activity() ) { 606 /* translators: %s: the page number. */ 607 $bp_title_parts['page'] = sprintf( __( 'Page %s', 'buddypress' ), max( $paged, $page ) ); 608 } 609 } 610 611 // Pad the separator with 1 space on each side. 612 $prefix = str_pad( $sep, strlen( $sep ) + 2, ' ', STR_PAD_BOTH ); 613 614 // Join the parts together. 615 $new_title = join( $prefix, array_filter( $bp_title_parts ) ); 616 617 // Append the prefix for pre `title-tag` compatibility. 618 if ( false === $title_tag_compatibility ) { 619 $new_title = $new_title . $prefix; 620 } 621 622 /** 623 * Filters the older 'wp_title' page title for BuddyPress pages. 624 * 625 * @since 1.5.0 626 * 627 * @param string $new_title The BuddyPress page title. 628 * @param string $title The original WordPress page title. 629 * @param string $sep The title parts separator. 630 * @param string $seplocation Location of the separator (left or right). 631 */ 632 return apply_filters( 'bp_modify_page_title', $new_title, $title, $sep, $seplocation ); 633 } 634 add_filter( 'wp_title', 'bp_modify_page_title', 20, 3 ); 635 add_filter( 'bp_modify_page_title', 'wptexturize' ); 636 add_filter( 'bp_modify_page_title', 'convert_chars' ); 637 add_filter( 'bp_modify_page_title', 'esc_html' ); 638 639 /** 640 * Filter the document title for BuddyPress pages. 641 * 642 * @since 2.4.3 643 * 644 * @param array $title The WordPress document title parts. 645 * @return array the unchanged title parts or the BuddyPress ones 646 */ 647 function bp_modify_document_title_parts( $title = array() ) { 648 // Get the BuddyPress title parts. 649 $bp_title_parts = bp_get_title_parts(); 650 651 // If not set, simply return the original title. 652 if ( ! $bp_title_parts ) { 653 return $title; 654 } 655 656 // Get the separator used by wp_get_document_title(). 657 $sep = apply_filters( 'document_title_separator', '-' ); 658 659 // Build the BuddyPress portion of the title. 660 // We don't need to sanitize this as WordPress will take care of it. 661 $bp_title = array( 662 'title' => join( " $sep ", $bp_title_parts ) 663 ); 664 665 // Add the pagination number if needed (not sure if this is necessary). 666 if ( isset( $title['page'] ) && ! bp_is_single_activity() ) { 667 $bp_title['page'] = $title['page']; 668 } 669 670 // Add the sitename if needed. 671 if ( isset( $title['site'] ) ) { 672 $bp_title['site'] = $title['site']; 673 } 674 675 /** 676 * Filters BuddyPress title parts that will be used into the document title. 677 * 678 * @since 2.4.3 679 * 680 * @param array $bp_title The BuddyPress page title parts. 681 * @param array $title The original WordPress title parts. 682 */ 683 return apply_filters( 'bp_modify_document_title_parts', $bp_title, $title ); 684 } 685 add_filter( 'document_title_parts', 'bp_modify_document_title_parts', 20, 1 ); 686 687 /** 688 * Add BuddyPress-specific items to the wp_nav_menu. 689 * 690 * @since 1.9.0 691 * 692 * @param WP_Post $menu_item The menu item. 693 * @return WP_Post The modified WP_Post object. 694 */ 695 function bp_setup_nav_menu_item( $menu_item ) { 696 if ( is_admin() ) { 697 if ( 'bp_nav_menu_item' === $menu_item->object ) { 698 $menu_item->type = 'custom'; 699 $menu_item->url = $menu_item->guid; 700 701 if ( ! in_array( array( 'bp-menu', 'bp-'. $menu_item->post_excerpt .'-nav' ), $menu_item->classes ) ) { 702 $menu_item->classes[] = 'bp-menu'; 703 $menu_item->classes[] = 'bp-'. $menu_item->post_excerpt .'-nav'; 704 } 705 } 706 707 return $menu_item; 708 } 709 710 // Prevent a notice error when using the customizer. 711 $menu_classes = $menu_item->classes; 712 713 if ( is_array( $menu_classes ) ) { 714 $menu_classes = implode( ' ', $menu_item->classes); 715 } 716 717 // We use information stored in the CSS class to determine what kind of 718 // menu item this is, and how it should be treated. 719 preg_match( '/\sbp-(.*)-nav/', $menu_classes, $matches ); 720 721 // If this isn't a BP menu item, we can stop here. 722 if ( empty( $matches[1] ) ) { 723 return $menu_item; 724 } 725 726 switch ( $matches[1] ) { 727 case 'login' : 728 if ( is_user_logged_in() ) { 729 $menu_item->_invalid = true; 730 } else { 731 $menu_item->url = wp_login_url( bp_get_requested_url() ); 732 } 733 734 break; 735 736 case 'logout' : 737 if ( ! is_user_logged_in() ) { 738 $menu_item->_invalid = true; 739 } else { 740 $menu_item->url = wp_logout_url( bp_get_requested_url() ); 741 } 742 743 break; 744 745 // Don't show the Register link to logged-in users. 746 case 'register' : 747 if ( is_user_logged_in() ) { 748 $menu_item->_invalid = true; 749 } 750 751 break; 752 753 // All other BP nav items are specific to the logged-in user, 754 // and so are not relevant to logged-out users. 755 default: 756 if ( is_user_logged_in() ) { 757 $menu_item->url = bp_nav_menu_get_item_url( $matches[1] ); 758 } else { 759 $menu_item->_invalid = true; 760 } 761 762 break; 763 } 764 765 // If component is deactivated, make sure menu item doesn't render. 766 if ( empty( $menu_item->url ) ) { 767 $menu_item->_invalid = true; 768 769 // Highlight the current page. 770 } else { 771 $current = bp_get_requested_url(); 772 if ( strpos( $current, $menu_item->url ) !== false ) { 773 if ( is_array( $menu_item->classes ) ) { 774 $menu_item->classes[] = 'current_page_item'; 775 $menu_item->classes[] = 'current-menu-item'; 776 } else { 777 $menu_item->classes = array( 'current_page_item', 'current-menu-item' ); 778 } 779 } 780 } 781 782 return $menu_item; 783 } 784 add_filter( 'wp_setup_nav_menu_item', 'bp_setup_nav_menu_item', 10, 1 ); 785 786 /** 787 * Populate BuddyPress user nav items for the customizer. 788 * 789 * @since 2.3.3 790 * 791 * @param array $items The array of menu items. 792 * @param string $type The requested type. 793 * @param string $object The requested object name. 794 * @param integer $page The page num being requested. 795 * @return array The paginated BuddyPress user nav items. 796 */ 797 function bp_customizer_nav_menus_get_items( $items = array(), $type = '', $object = '', $page = 0 ) { 798 if ( 'bp_loggedin_nav' === $object ) { 799 $bp_items = bp_nav_menu_get_loggedin_pages(); 800 } elseif ( 'bp_loggedout_nav' === $object ) { 801 $bp_items = bp_nav_menu_get_loggedout_pages(); 802 } else { 803 return $items; 804 } 805 806 foreach ( $bp_items as $bp_item ) { 807 $items[] = array( 808 'id' => "bp-{$bp_item->post_excerpt}", 809 'title' => html_entity_decode( $bp_item->post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ), 810 'type' => $type, 811 'url' => esc_url_raw( $bp_item->guid ), 812 'classes' => "bp-menu bp-{$bp_item->post_excerpt}-nav", 813 'type_label' => _x( 'Custom Link', 'customizer menu type label', 'buddypress' ), 814 'object' => $object, 815 'object_id' => -1, 816 ); 817 } 818 819 return array_slice( $items, 10 * $page, 10 ); 820 } 821 add_filter( 'customize_nav_menu_available_items', 'bp_customizer_nav_menus_get_items', 10, 4 ); 822 823 /** 824 * Set BuddyPress item navs for the customizer. 825 * 826 * @since 2.3.3 827 * 828 * @param array $item_types An associative array structured for the customizer. 829 * @return array $item_types An associative array structured for the customizer. 830 */ 831 function bp_customizer_nav_menus_set_item_types( $item_types = array() ) { 832 $item_types = array_merge( $item_types, array( 833 'bp_loggedin_nav' => array( 834 'title' => _x( 'BuddyPress (logged-in)', 'customizer menu section title', 'buddypress' ), 835 'type' => 'bp_nav', 836 'object' => 'bp_loggedin_nav', 837 ), 838 'bp_loggedout_nav' => array( 839 'title' => _x( 'BuddyPress (logged-out)', 'customizer menu section title', 'buddypress' ), 840 'type' => 'bp_nav', 841 'object' => 'bp_loggedout_nav', 842 ), 843 ) ); 844 845 return $item_types; 846 } 847 add_filter( 'customize_nav_menu_available_item_types', 'bp_customizer_nav_menus_set_item_types', 10, 1 ); 848 849 /** 850 * Filter SQL query strings to swap out the 'meta_id' column. 851 * 852 * WordPress uses the meta_id column for commentmeta and postmeta, and so 853 * hardcodes the column name into its *_metadata() functions. BuddyPress, on 854 * the other hand, uses 'id' for the primary column. To make WP's functions 855 * usable for BuddyPress, we use this just-in-time filter on 'query' to swap 856 * 'meta_id' with 'id. 857 * 858 * @since 2.0.0 859 * 860 * @access private Do not use. 861 * 862 * @param string $q SQL query. 863 * @return string 864 */ 865 function bp_filter_metaid_column_name( $q ) { 866 /* 867 * Replace quoted content with __QUOTE__ to avoid false positives. 868 * This regular expression will match nested quotes. 869 */ 870 $quoted_regex = "/'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'/s"; 871 preg_match_all( $quoted_regex, $q, $quoted_matches ); 872 $q = preg_replace( $quoted_regex, '__QUOTE__', $q ); 873 874 $q = str_replace( 'meta_id', 'id', $q ); 875 876 // Put quoted content back into the string. 877 if ( ! empty( $quoted_matches[0] ) ) { 878 for ( $i = 0; $i < count( $quoted_matches[0] ); $i++ ) { 879 $quote_pos = strpos( $q, '__QUOTE__' ); 880 $q = substr_replace( $q, $quoted_matches[0][ $i ], $quote_pos, 9 ); 881 } 882 } 883 884 return $q; 885 } 886 887 /** 888 * Filter the edit post link to avoid its display in BuddyPress pages. 889 * 890 * @since 2.1.0 891 * 892 * @param string $edit_link The edit link. 893 * @param int $post_id Post ID. 894 * @return false|string Will be a boolean (false) if $post_id is 0. Will be a string (the unchanged edit link) 895 * otherwise 896 */ 897 function bp_core_filter_edit_post_link( $edit_link = '', $post_id = 0 ) { 898 if ( 0 === $post_id ) { 899 $edit_link = false; 900 } 901 902 return $edit_link; 903 } 904 905 /** 906 * Add 'loading="lazy"' attribute into images and iframes. 907 * 908 * @since 7.0.0 909 * 910 * @string $content Content to inject attribute into. 911 * @return string 912 */ 913 function bp_core_add_loading_lazy_attribute( $content = '' ) { 914 if ( false === strpos( $content, '<img ' ) && false === strpos( $content, '<iframe ' ) ) { 915 return $content; 916 } 917 918 $content = str_replace( '<img ', '<img loading="lazy" ', $content ); 919 $content = str_replace( '<iframe ', '<iframe loading="lazy" ', $content ); 920 921 // WordPress posts need their position absolute removed for lazyloading. 922 $find_pos_absolute = ' style="position: absolute; clip: rect(1px, 1px, 1px, 1px);" '; 923 if ( false !== strpos( $content, 'data-secret=' ) && false !== strpos( $content, $find_pos_absolute ) ) { 924 $content = str_replace( $find_pos_absolute, '', $content ); 925 } 926 927 return $content; 928 } 929 930 /** 931 * Should BuddyPress load the mentions scripts and related assets, including results to prime the 932 * mentions suggestions? 933 * 934 * @since 2.2.0 935 * 936 * @param bool $load_mentions True to load mentions assets, false otherwise. 937 * @param bool $mentions_enabled True if mentions are enabled. 938 * @return bool True if mentions scripts should be loaded. 939 */ 940 function bp_maybe_load_mentions_scripts_for_blog_content( $load_mentions, $mentions_enabled ) { 941 if ( ! $mentions_enabled ) { 942 return $load_mentions; 943 } 944 945 if ( $load_mentions || ( bp_is_blog_page() && is_singular() && comments_open() ) ) { 946 return true; 947 } 948 949 return $load_mentions; 950 } 951 add_filter( 'bp_activity_maybe_load_mentions_scripts', 'bp_maybe_load_mentions_scripts_for_blog_content', 10, 2 ); 952 953 /** 954 * Injects specific BuddyPress CSS classes into a widget sidebar. 955 * 956 * Helps to standardize styling of BuddyPress widgets within a theme that 957 * does not use dynamic CSS classes in their widget sidebar's 'before_widget' 958 * call. 959 * 960 * @since 2.4.0 961 * @access private 962 * 963 * @global array $wp_registered_widgets Current registered widgets. 964 * 965 * @param array $params Current sidebar params. 966 * @return array 967 */ 968 function _bp_core_inject_bp_widget_css_class( $params ) { 969 global $wp_registered_widgets; 970 971 $widget_id = $params[0]['widget_id']; 972 973 // If callback isn't an array, bail. 974 if ( false === is_array( $wp_registered_widgets[ $widget_id ]['callback'] ) ) { 975 return $params; 976 } 977 978 // If the current widget isn't a BuddyPress one, stop! 979 // We determine if a widget is a BuddyPress widget, if the widget class 980 // begins with 'bp_'. 981 if ( 0 !== strpos( $wp_registered_widgets[ $widget_id ]['callback'][0]->id_base, 'bp_' ) ) { 982 return $params; 983 } 984 985 // Dynamically add our widget CSS classes for BP widgets if not already there. 986 $classes = array(); 987 988 // Try to find 'widget' CSS class. 989 if ( false === strpos( $params[0]['before_widget'], 'widget ' ) ) { 990 $classes[] = 'widget'; 991 } 992 993 // Try to find 'buddypress' CSS class. 994 if ( false === strpos( $params[0]['before_widget'], ' buddypress' ) ) { 995 $classes[] = 'buddypress'; 996 } 997 998 // Stop if widget already has our CSS classes. 999 if ( empty( $classes ) ) { 1000 return $params; 1001 } 1002 1003 // CSS injection time! 1004 $params[0]['before_widget'] = str_replace( 'class="', 'class="' . implode( ' ', $classes ) . ' ', $params[0]['before_widget'] ); 1005 1006 return $params; 1007 } 1008 add_filter( 'dynamic_sidebar_params', '_bp_core_inject_bp_widget_css_class' ); 1009 1010 /** 1011 * Add email link styles to rendered email template. 1012 * 1013 * This is only used when the email content has been merged into the email template. 1014 * 1015 * @since 2.5.0 1016 * 1017 * @param string $value Property value. 1018 * @param string $property_name Email template property name. 1019 * @param string $transform How the return value was transformed. 1020 * @return string Updated value. 1021 */ 1022 function bp_email_add_link_color_to_template( $value, $property_name, $transform ) { 1023 if ( $property_name !== 'template' || $transform !== 'add-content' ) { 1024 return $value; 1025 } 1026 1027 $settings = bp_email_get_appearance_settings(); 1028 $replacement = 'style="color: ' . esc_attr( $settings['link_text_color'] ) . ';'; 1029 1030 // Find all links. 1031 preg_match_all( '#<a[^>]+>#i', $value, $links, PREG_SET_ORDER ); 1032 foreach ( $links as $link ) { 1033 $new_link = $link = array_shift( $link ); 1034 1035 // Add/modify style property. 1036 if ( strpos( $link, 'style="' ) !== false ) { 1037 $new_link = str_replace( 'style="', $replacement, $link ); 1038 } else { 1039 $new_link = str_replace( '<a ', "<a {$replacement}\" ", $link ); 1040 } 1041 1042 if ( $new_link !== $link ) { 1043 $value = str_replace( $link, $new_link, $value ); 1044 } 1045 } 1046 1047 return $value; 1048 } 1049 add_filter( 'bp_email_get_property', 'bp_email_add_link_color_to_template', 6, 3 ); 1050 1051 /** 1052 * Add custom headers to outgoing emails. 1053 * 1054 * @since 2.5.0 1055 * 1056 * @param array $headers Array of email headers. 1057 * @param string $property Name of property. Unused. 1058 * @param string $transform Return value transformation. Unused. 1059 * @param BP_Email $email Email object reference. 1060 * @return array 1061 */ 1062 function bp_email_set_default_headers( $headers, $property, $transform, $email ) { 1063 $headers['X-BuddyPress'] = bp_get_version(); 1064 $headers['X-BuddyPress-Type'] = $email->get( 'type' ); 1065 1066 $tokens = $email->get_tokens(); 1067 1068 // Add 'List-Unsubscribe' header if applicable. 1069 if ( ! empty( $tokens['unsubscribe'] ) && $tokens['unsubscribe'] !== wp_login_url() ) { 1070 $user = get_user_by( 'email', $tokens['recipient.email'] ); 1071 1072 $link = bp_email_get_unsubscribe_link( array( 1073 'user_id' => $user->ID, 1074 'notification_type' => $email->get( 'type' ), 1075 ) ); 1076 1077 if ( ! empty( $link ) ) { 1078 $headers['List-Unsubscribe'] = sprintf( '<%s>', esc_url_raw( $link ) ); 1079 } 1080 } 1081 1082 return $headers; 1083 } 1084 add_filter( 'bp_email_get_headers', 'bp_email_set_default_headers', 6, 4 ); 1085 1086 /** 1087 * Add default email tokens. 1088 * 1089 * @since 2.5.0 1090 * 1091 * @param array $tokens Email tokens. 1092 * @param string $property_name Unused. 1093 * @param string $transform Unused. 1094 * @param BP_Email $email Email being sent. 1095 * @return array 1096 */ 1097 function bp_email_set_default_tokens( $tokens, $property_name, $transform, $email ) { 1098 $tokens['site.admin-email'] = bp_get_option( 'admin_email' ); 1099 $tokens['site.url'] = bp_get_root_domain(); 1100 $tokens['email.subject'] = $email->get_subject(); 1101 1102 // These options are escaped with esc_html on the way into the database in sanitize_option(). 1103 $tokens['site.description'] = wp_specialchars_decode( bp_get_option( 'blogdescription' ), ENT_QUOTES ); 1104 $tokens['site.name'] = wp_specialchars_decode( bp_get_option( 'blogname' ), ENT_QUOTES ); 1105 1106 // Default values for tokens set conditionally below. 1107 $tokens['email.preheader'] = ''; 1108 $tokens['recipient.email'] = ''; 1109 $tokens['recipient.name'] = ''; 1110 $tokens['recipient.username'] = ''; 1111 1112 // Who is the email going to? 1113 $recipient = $email->get( 'to' ); 1114 if ( $recipient ) { 1115 $recipient = array_shift( $recipient ); 1116 $user_obj = $recipient->get_user( 'search-email' ); 1117 1118 $tokens['recipient.email'] = $recipient->get_address(); 1119 $tokens['recipient.name'] = $recipient->get_name(); 1120 1121 if ( ! $user_obj && $tokens['recipient.email'] ) { 1122 $user_obj = get_user_by( 'email', $tokens['recipient.email'] ); 1123 } 1124 1125 if ( $user_obj ) { 1126 $tokens['recipient.username'] = $user_obj->user_login; 1127 1128 if ( bp_is_active( 'settings' ) && empty( $tokens['unsubscribe'] ) ) { 1129 $tokens['unsubscribe'] = esc_url( sprintf( 1130 '%s%s/notifications/', 1131 bp_core_get_user_domain( $user_obj->ID ), 1132 bp_get_settings_slug() 1133 ) ); 1134 } 1135 } 1136 } 1137 1138 // Set default unsubscribe link if not passed. 1139 if ( empty( $tokens['unsubscribe'] ) ) { 1140 $tokens['unsubscribe'] = wp_login_url(); 1141 } 1142 1143 // Email preheader. 1144 $preheader = $email->get_preheader(); 1145 if ( $preheader ) { 1146 $tokens['email.preheader'] = $preheader; 1147 } 1148 1149 return $tokens; 1150 } 1151 add_filter( 'bp_email_get_tokens', 'bp_email_set_default_tokens', 6, 4 ); 1152 1153 /** 1154 * Find and render the template for Email posts (the Customizer and admin previews). 1155 * 1156 * Misuses the `template_include` filter which expects a string, but as we need to replace 1157 * the `{{{content}}}` token with the post's content, we use object buffering to load the 1158 * template, replace the token, and render it. 1159 * 1160 * The function returns an empty string to prevent WordPress rendering another template. 1161 * 1162 * @since 2.5.0 1163 * 1164 * @param string $template Path to template (probably single.php). 1165 * @return string 1166 */ 1167 function bp_core_render_email_template( $template ) { 1168 if ( get_post_type() !== bp_get_email_post_type() || ! is_single() ) { 1169 return $template; 1170 } 1171 1172 /** 1173 * Filter template used to display Email posts. 1174 * 1175 * @since 2.5.0 1176 * 1177 * @param string $template Path to current template (probably single.php). 1178 */ 1179 $email_template = apply_filters( 'bp_core_render_email_template', 1180 bp_locate_template( bp_email_get_template( get_queried_object() ), false ), 1181 $template 1182 ); 1183 1184 if ( ! $email_template ) { 1185 return $template; 1186 } 1187 1188 ob_start(); 1189 include( $email_template ); 1190 $template = ob_get_contents(); 1191 ob_end_clean(); 1192 1193 // Make sure we add a <title> tag so WP Customizer picks it up. 1194 $template = str_replace( '<head>', '<head><title>' . esc_html_x( 'BuddyPress Emails', 'screen heading', 'buddypress' ) . '</title>', $template ); 1195 echo str_replace( '{{{content}}}', wpautop( get_post()->post_content ), $template ); 1196 1197 /* 1198 * Link colours are applied directly in the email template before sending, so we 1199 * need to add an extra style here to set the colour for the Customizer or preview. 1200 */ 1201 $settings = bp_email_get_appearance_settings(); 1202 printf( 1203 '<style>a { color: %s; }</style>', 1204 esc_attr( $settings['highlight_color'] ) 1205 ); 1206 1207 return ''; 1208 } 1209 add_action( 'bp_template_include', 'bp_core_render_email_template', 12 ); 1210 1211 /** 1212 * Adds BuddyPress components' slugs to the WordPress Multisite subdirectory reserved names. 1213 * 1214 * @since 6.0.0 1215 * 1216 * @param array $names The WordPress Multisite subdirectory reserved names. 1217 * @return array The WordPress & BuddyPress Multisite subdirectory reserved names. 1218 */ 1219 function bp_core_components_subdirectory_reserved_names( $names = array() ) { 1220 $bp_pages = (array) buddypress()->pages; 1221 1222 return array_merge( $names, wp_list_pluck( $bp_pages, 'slug' ) ); 1223 } 1224 add_filter( 'subdirectory_reserved_names', 'bp_core_components_subdirectory_reserved_names' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Mar 1 01:01:37 2021 | Cross-referenced by PHPXref 0.7.1 |