[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Functions of BuddyPress's Legacy theme. 4 * 5 * @since 1.7.0 6 * 7 * @package BuddyPress 8 * @subpackage BP_Theme_Compat 9 * @version 10.0.0 10 */ 11 12 // Exit if accessed directly. 13 defined( 'ABSPATH' ) || exit; 14 15 /** Theme Setup ***************************************************************/ 16 17 if ( !class_exists( 'BP_Legacy' ) ) : 18 19 /** 20 * Loads BuddyPress Legacy Theme functionality. 21 * 22 * This is not a real theme by WordPress standards, and is instead used as the 23 * fallback for any WordPress theme that does not have BuddyPress templates in it. 24 * 25 * To make your custom theme BuddyPress compatible and customize the templates, you 26 * can copy these files into your theme without needing to merge anything 27 * together; BuddyPress should safely handle the rest. 28 * 29 * See @link BP_Theme_Compat() for more. 30 * 31 * @since 1.7.0 32 * 33 * @package BuddyPress 34 * @subpackage BP_Theme_Compat 35 */ 36 class BP_Legacy extends BP_Theme_Compat { 37 38 /** Functions *************************************************************/ 39 40 /** 41 * The main BuddyPress (Legacy) Loader. 42 * 43 * @since 1.7.0 44 * 45 */ 46 public function __construct() { 47 parent::start(); 48 } 49 50 /** 51 * Component global variables. 52 * 53 * You'll want to customize the values in here, so they match whatever your 54 * needs are. 55 * 56 * @since 1.7.0 57 */ 58 protected function setup_globals() { 59 $bp = buddypress(); 60 $this->id = 'legacy'; 61 $this->name = __( 'BuddyPress Legacy', 'buddypress' ); 62 $this->version = bp_get_version(); 63 $this->dir = trailingslashit( $bp->themes_dir . '/bp-legacy' ); 64 $this->url = trailingslashit( $bp->themes_url . '/bp-legacy' ); 65 } 66 67 /** 68 * Setup the theme hooks. 69 * 70 * @since 1.7.0 71 * 72 */ 73 protected function setup_actions() { 74 75 // Template Output. 76 add_filter( 'bp_get_activity_action_pre_meta', array( $this, 'secondary_avatars' ), 10, 2 ); 77 78 // Filter BuddyPress template hierarchy and look for page templates. 79 add_filter( 'bp_get_buddypress_template', array( $this, 'theme_compat_page_templates' ), 10, 1 ); 80 81 /** Scripts ***********************************************************/ 82 83 add_action( 'bp_enqueue_scripts', array( $this, 'enqueue_styles' ) ); // Enqueue theme CSS 84 add_action( 'bp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); // Enqueue theme JS 85 add_filter( 'bp_enqueue_scripts', array( $this, 'localize_scripts' ) ); // Enqueue theme script localization 86 87 /** Body no-js Class **************************************************/ 88 89 add_filter( 'body_class', array( $this, 'add_nojs_body_class' ), 20, 1 ); 90 91 /** Buttons ***********************************************************/ 92 93 if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) { 94 // Register buttons for the relevant component templates 95 // Friends button. 96 if ( bp_is_active( 'friends' ) ) 97 add_action( 'bp_member_header_actions', 'bp_add_friend_button', 5 ); 98 99 // Activity button. 100 if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() ) 101 add_action( 'bp_member_header_actions', 'bp_send_public_message_button', 20 ); 102 103 // Messages button. 104 if ( bp_is_active( 'messages' ) ) 105 add_action( 'bp_member_header_actions', 'bp_send_private_message_button', 20 ); 106 107 // Group buttons. 108 if ( bp_is_active( 'groups' ) ) { 109 add_action( 'bp_group_header_actions', 'bp_group_join_button', 5 ); 110 add_action( 'bp_directory_groups_actions', 'bp_group_join_button' ); 111 add_action( 'bp_groups_directory_group_filter', 'bp_legacy_theme_group_create_nav', 999 ); 112 add_action( 'bp_after_group_admin_content', 'bp_legacy_groups_admin_screen_hidden_input' ); 113 add_action( 'bp_before_group_admin_form', 'bp_legacy_theme_group_manage_members_add_search' ); 114 } 115 116 // Blog button. 117 if ( bp_is_active( 'blogs' ) ) { 118 add_action( 'bp_directory_blogs_actions', 'bp_blogs_visit_blog_button' ); 119 add_action( 'bp_blogs_directory_blog_types', 'bp_legacy_theme_blog_create_nav', 999 ); 120 } 121 } 122 123 /** Notices ***********************************************************/ 124 125 // Only hook the 'sitewide_notices' overlay if the Sitewide 126 // Notices widget is not in use (to avoid duplicate content). 127 if ( bp_is_active( 'messages' ) && ! bp_is_widget_block_active( 'bp/sitewide-notices', 'bp_messages_sitewide_notices_widget', true ) ) { 128 add_action( 'wp_footer', array( $this, 'sitewide_notices' ), 9999 ); 129 } 130 131 /** Ajax **************************************************************/ 132 133 $actions = array( 134 135 // Directory filters. 136 'blogs_filter' => 'bp_legacy_theme_object_template_loader', 137 'forums_filter' => 'bp_legacy_theme_object_template_loader', 138 'groups_filter' => 'bp_legacy_theme_object_template_loader', 139 'members_filter' => 'bp_legacy_theme_object_template_loader', 140 'messages_filter' => 'bp_legacy_theme_messages_template_loader', 141 'invite_filter' => 'bp_legacy_theme_invite_template_loader', 142 'requests_filter' => 'bp_legacy_theme_requests_template_loader', 143 144 // Friends. 145 'accept_friendship' => 'bp_legacy_theme_ajax_accept_friendship', 146 'addremove_friend' => 'bp_legacy_theme_ajax_addremove_friend', 147 'reject_friendship' => 'bp_legacy_theme_ajax_reject_friendship', 148 149 // Activity. 150 'activity_get_older_updates' => 'bp_legacy_theme_activity_template_loader', 151 'activity_mark_fav' => 'bp_legacy_theme_mark_activity_favorite', 152 'activity_mark_unfav' => 'bp_legacy_theme_unmark_activity_favorite', 153 'activity_widget_filter' => 'bp_legacy_theme_activity_template_loader', 154 'delete_activity' => 'bp_legacy_theme_delete_activity', 155 'delete_activity_comment' => 'bp_legacy_theme_delete_activity_comment', 156 'get_single_activity_content' => 'bp_legacy_theme_get_single_activity_content', 157 'new_activity_comment' => 'bp_legacy_theme_new_activity_comment', 158 'post_update' => 'bp_legacy_theme_post_update', 159 'bp_spam_activity' => 'bp_legacy_theme_spam_activity', 160 'bp_spam_activity_comment' => 'bp_legacy_theme_spam_activity', 161 162 // Groups. 163 'groups_invite_user' => 'bp_legacy_theme_ajax_invite_user', 164 'joinleave_group' => 'bp_legacy_theme_ajax_joinleave_group', 165 166 // Messages. 167 'messages_autocomplete_results' => 'bp_legacy_theme_ajax_messages_autocomplete_results', 168 'messages_close_notice' => 'bp_legacy_theme_ajax_close_notice', 169 'messages_delete' => 'bp_legacy_theme_ajax_messages_delete', 170 'messages_markread' => 'bp_legacy_theme_ajax_message_markread', 171 'messages_markunread' => 'bp_legacy_theme_ajax_message_markunread', 172 'messages_send_reply' => 'bp_legacy_theme_ajax_messages_send_reply', 173 ); 174 175 // Conditional actions. 176 if ( bp_is_active( 'messages', 'star' ) ) { 177 $actions['messages_star'] = 'bp_legacy_theme_ajax_messages_star_handler'; 178 } 179 180 /** 181 * Register all of these AJAX handlers. 182 * 183 * The "wp_ajax_" action is used for logged in users, and "wp_ajax_nopriv_" 184 * executes for users that aren't logged in. This is for backpat with BP <1.6. 185 */ 186 foreach( $actions as $name => $function ) { 187 add_action( 'wp_ajax_' . $name, $function ); 188 add_action( 'wp_ajax_nopriv_' . $name, $function ); 189 } 190 191 add_filter( 'bp_ajax_querystring', 'bp_legacy_theme_ajax_querystring', 10, 2 ); 192 193 /** Override **********************************************************/ 194 195 /** 196 * Fires after all of the BuddyPress theme compat actions have been added. 197 * 198 * @since 1.7.0 199 * 200 * @param BP_Legacy $this Current BP_Legacy instance. 201 */ 202 do_action_ref_array( 'bp_theme_compat_actions', array( &$this ) ); 203 } 204 205 /** 206 * Load the theme CSS 207 * 208 * @since 1.7.0 209 * @since 2.3.0 Support custom CSS file named after the current theme or parent theme. 210 * 211 */ 212 public function enqueue_styles() { 213 $min = bp_core_get_minified_asset_suffix(); 214 215 // Locate the BP stylesheet. 216 $ltr = $this->locate_asset_in_stack( "buddypress{$min}.css", 'css' ); 217 218 // LTR. 219 if ( ! is_rtl() && isset( $ltr['location'], $ltr['handle'] ) ) { 220 wp_enqueue_style( $ltr['handle'], $ltr['location'], array(), $this->version, 'screen' ); 221 222 if ( $min ) { 223 wp_style_add_data( $ltr['handle'], 'suffix', $min ); 224 } 225 } 226 227 // RTL. 228 if ( is_rtl() ) { 229 $rtl = $this->locate_asset_in_stack( "buddypress-rtl{$min}.css", 'css' ); 230 231 if ( isset( $rtl['location'], $rtl['handle'] ) ) { 232 $rtl['handle'] = str_replace( '-css', '-css-rtl', $rtl['handle'] ); // Backwards compatibility. 233 wp_enqueue_style( $rtl['handle'], $rtl['location'], array(), $this->version, 'screen' ); 234 235 if ( $min ) { 236 wp_style_add_data( $rtl['handle'], 'suffix', $min ); 237 } 238 } 239 } 240 241 // Compatibility stylesheets for specific themes. 242 $theme = $this->locate_asset_in_stack( get_template() . "{$min}.css", 'css' ); 243 if ( ! is_rtl() && isset( $theme['location'] ) ) { 244 // Use a unique handle. 245 $theme['handle'] = 'bp-' . get_template(); 246 wp_enqueue_style( $theme['handle'], $theme['location'], array(), $this->version, 'screen' ); 247 248 if ( $min ) { 249 wp_style_add_data( $theme['handle'], 'suffix', $min ); 250 } 251 } 252 253 // Compatibility stylesheet for specific themes, RTL-version. 254 if ( is_rtl() ) { 255 $theme_rtl = $this->locate_asset_in_stack( get_template() . "-rtl{$min}.css", 'css' ); 256 257 if ( isset( $theme_rtl['location'] ) ) { 258 $theme_rtl['handle'] = $theme['handle'] . '-rtl'; 259 wp_enqueue_style( $theme_rtl['handle'], $theme_rtl['location'], array(), $this->version, 'screen' ); 260 261 if ( $min ) { 262 wp_style_add_data( $theme_rtl['handle'], 'suffix', $min ); 263 } 264 } 265 } 266 } 267 268 /** 269 * Enqueue the required JavaScript files 270 * 271 * @since 1.7.0 272 */ 273 public function enqueue_scripts() { 274 $min = bp_core_get_minified_asset_suffix(); 275 276 // Locate the BP JS file. 277 $asset = $this->locate_asset_in_stack( "buddypress{$min}.js", 'js' ); 278 279 // Enqueue the global JS, if found - AJAX will not work 280 // without it. 281 if ( isset( $asset['location'], $asset['handle'] ) ) { 282 wp_enqueue_script( $asset['handle'], $asset['location'], bp_core_get_js_dependencies(), $this->version ); 283 } 284 285 /** 286 * Filters whether directory filter settings ('scope', etc) should be stored in a persistent cookie. 287 * 288 * @since 4.0.0 289 * 290 * @param bool $store_filter_settings Whether to store settings. Defaults to true for logged-in users. 291 */ 292 $store_filter_settings = apply_filters( 'bp_legacy_store_filter_settings', is_user_logged_in() ); 293 294 /** 295 * Filters core JavaScript strings for internationalization before AJAX usage. 296 * 297 * @since 2.0.0 298 * 299 * @param array $value Array of key/value pairs for AJAX usage. 300 */ 301 $params = apply_filters( 'bp_core_get_js_strings', array( 302 // Strings for display. 303 'accepted' => __( 'Accepted', 'buddypress' ), 304 'close' => __( 'Close', 'buddypress' ), 305 'comments' => __( 'comments', 'buddypress' ), 306 'leave_group_confirm' => __( 'Are you sure you want to leave this group?', 'buddypress' ), 307 'mark_as_fav' => __( 'Favorite', 'buddypress' ), 308 'my_favs' => __( 'My Favorites', 'buddypress' ), 309 'rejected' => __( 'Rejected', 'buddypress' ), 310 'remove_fav' => __( 'Remove Favorite', 'buddypress' ), 311 'show_all' => __( 'Show all', 'buddypress' ), 312 'show_all_comments' => __( 'Show all comments for this thread', 'buddypress' ), 313 314 /* translators: %s: number of activity comments */ 315 'show_x_comments' => __( 'Show all comments (%d)', 'buddypress' ), 316 'unsaved_changes' => __( 'Your profile has unsaved changes. If you leave the page, the changes will be lost.', 'buddypress' ), 317 'view' => __( 'View', 'buddypress' ), 318 319 // Settings. 320 'store_filter_settings' => $store_filter_settings, 321 ) ); 322 wp_localize_script( $asset['handle'], 'BP_DTheme', $params ); 323 324 // Maybe enqueue comment reply JS. 325 if ( is_singular() && bp_is_blog_page() && get_option( 'thread_comments' ) ) { 326 wp_enqueue_script( 'comment-reply' ); 327 } 328 329 // Maybe enqueue password verify JS (register page or user settings page). 330 if ( bp_is_register_page() || ( function_exists( 'bp_is_user_settings_general' ) && bp_is_user_settings_general() ) ) { 331 332 // Locate the Register Page JS file. 333 $asset = $this->locate_asset_in_stack( "password-verify{$min}.js", 'js', 'bp-legacy-password-verify' ); 334 335 $dependencies = array_merge( bp_core_get_js_dependencies(), array( 336 'password-strength-meter', 337 ) ); 338 339 // Enqueue script. 340 wp_enqueue_script( $asset['handle'] . '-password-verify', $asset['location'], $dependencies, $this->version ); 341 wp_localize_script( 342 $asset['handle'] . '-password-verify', 343 'bpPasswordVerify', 344 array( 345 'tooWeakPasswordWarning' => __( 'Your password is too weak, please use a stronger password.', 'buddypress' ), 346 'requiredPassStrength' => bp_members_user_pass_required_strength(), 347 ) 348 ); 349 } 350 351 // Star private messages. 352 if ( bp_is_active( 'messages', 'star' ) && bp_is_user_messages() ) { 353 wp_localize_script( $asset['handle'], 'BP_PM_Star', array( 354 'strings' => array( 355 'text_unstar' => __( 'Unstar', 'buddypress' ), 356 'text_star' => __( 'Star', 'buddypress' ), 357 'title_unstar' => __( 'Starred', 'buddypress' ), 358 'title_star' => __( 'Not starred', 'buddypress' ), 359 'title_unstar_thread' => __( 'Remove all starred messages in this thread', 'buddypress' ), 360 'title_star_thread' => __( 'Star the first message in this thread', 'buddypress' ), 361 ), 362 'is_single_thread' => (int) bp_is_messages_conversation(), 363 'star_counter' => 0, 364 'unstar_counter' => 0 365 ) ); 366 } 367 } 368 369 /** 370 * Get the URL and handle of a web-accessible CSS or JS asset 371 * 372 * We provide two levels of customizability with respect to where CSS 373 * and JS files can be stored: (1) the child theme/parent theme/theme 374 * compat hierarchy, and (2) the "template stack" of /buddypress/css/, 375 * /community/css/, and /css/. In this way, CSS and JS assets can be 376 * overloaded, and default versions provided, in exactly the same way 377 * as corresponding PHP templates. 378 * 379 * We are duplicating some of the logic that is currently found in 380 * bp_locate_template() and the _template_stack() functions. Those 381 * functions were built with PHP templates in mind, and will require 382 * refactoring in order to provide "stack" functionality for assets 383 * that must be accessible both using file_exists() (the file path) 384 * and at a public URI. 385 * 386 * This method is marked private, with the understanding that the 387 * implementation is subject to change or removal in an upcoming 388 * release, in favor of a unified _template_stack() system. Plugin 389 * and theme authors should not attempt to use what follows. 390 * 391 * @since 1.8.0 392 * @param string $file A filename like buddypress.css. 393 * @param string $type Optional. Either "js" or "css" (the default). 394 * @param string $script_handle Optional. If set, used as the script name in `wp_enqueue_script`. 395 * @return array An array of data for the wp_enqueue_* function: 396 * 'handle' (eg 'bp-child-css') and a 'location' (the URI of the 397 * asset) 398 */ 399 private function locate_asset_in_stack( $file, $type = 'css', $script_handle = '' ) { 400 $locations = array(); 401 402 // Ensure the assets can be located when running from /src/. 403 if ( defined( 'BP_SOURCE_SUBDIRECTORY' ) && BP_SOURCE_SUBDIRECTORY === 'src' ) { 404 $file = str_replace( '.min', '', $file ); 405 } 406 407 // No need to check child if template == stylesheet. 408 if ( is_child_theme() ) { 409 $locations[] = array( 410 'type' => 'bp-child', 411 'dir' => get_stylesheet_directory(), 412 'uri' => get_stylesheet_directory_uri(), 413 'file' => $file, 414 ); 415 416 $locations[] = array( 417 'type' => 'bp-child', 418 'dir' => get_stylesheet_directory(), 419 'uri' => get_stylesheet_directory_uri(), 420 'file' => str_replace( '.min', '', $file ), 421 ); 422 } 423 424 $locations[] = array( 425 'type' => 'bp-parent', 426 'dir' => get_template_directory(), 427 'uri' => get_template_directory_uri(), 428 'file' => str_replace( '.min', '', $file ), 429 ); 430 431 $locations[] = array( 432 'type' => 'bp-legacy', 433 'dir' => bp_get_theme_compat_dir(), 434 'uri' => bp_get_theme_compat_url(), 435 'file' => $file, 436 ); 437 438 // Subdirectories within the top-level $locations directories. 439 $subdirs = array( 440 'buddypress/' . $type, 441 'community/' . $type, 442 $type, 443 ); 444 445 $retval = array(); 446 447 foreach ( $locations as $location ) { 448 foreach ( $subdirs as $subdir ) { 449 if ( file_exists( trailingslashit( $location['dir'] ) . trailingslashit( $subdir ) . $location['file'] ) ) { 450 $retval['location'] = trailingslashit( $location['uri'] ) . trailingslashit( $subdir ) . $location['file']; 451 $retval['handle'] = ( $script_handle ) ? $script_handle : "{$location['type']}-{$type}"; 452 453 break 2; 454 } 455 } 456 } 457 458 return $retval; 459 } 460 461 /** 462 * Adds the no-js class to the body tag. 463 * 464 * This function ensures that the <body> element will have the 'no-js' class by default. If you're 465 * using JavaScript for some visual functionality in your theme, and you want to provide noscript 466 * support, apply those styles to body.no-js. 467 * 468 * The no-js class is removed by the JavaScript created in buddypress.js. 469 * 470 * @since 1.7.0 471 * 472 * @param array $classes Array of classes to append to body tag. 473 * @return array $classes 474 */ 475 public function add_nojs_body_class( $classes ) { 476 if ( ! in_array( 'no-js', $classes ) ) 477 $classes[] = 'no-js'; 478 479 return array_unique( $classes ); 480 } 481 482 /** 483 * Load localizations for topic script. 484 * 485 * These localizations require information that may not be loaded even by init. 486 * 487 * @since 1.7.0 488 */ 489 public function localize_scripts() { 490 } 491 492 /** 493 * Outputs sitewide notices markup in the footer. 494 * 495 * @since 1.7.0 496 * 497 * @see https://buddypress.trac.wordpress.org/ticket/4802 498 */ 499 public function sitewide_notices() { 500 // Do not show notices if user is not logged in. 501 if ( ! is_user_logged_in() || is_admin() ) { 502 return; 503 } 504 505 // Add a class to determine if the admin bar is on or not. 506 $class = did_action( 'admin_bar_menu' ) ? 'admin-bar-on' : 'admin-bar-off'; 507 508 echo '<div id="sitewide-notice" class="' . $class . '">'; 509 bp_message_get_notices(); 510 echo '</div>'; 511 } 512 513 /** 514 * Add secondary avatar image to this activity stream's record, if supported. 515 * 516 * @since 1.7.0 517 * 518 * @param string $action The text of this activity. 519 * @param BP_Activity_Activity $activity Activity object. 520 * @return string 521 */ 522 function secondary_avatars( $action, $activity ) { 523 switch ( $activity->component ) { 524 case 'groups' : 525 case 'friends' : 526 // Only insert avatar if one exists. 527 if ( $secondary_avatar = bp_get_activity_secondary_avatar() ) { 528 $reverse_content = strrev( $action ); 529 $position = strpos( $reverse_content, 'a<' ); 530 $action = substr_replace( $action, $secondary_avatar, -$position - 2, 0 ); 531 } 532 break; 533 } 534 535 return $action; 536 } 537 538 /** 539 * Filter the default theme compatibility root template hierarchy, and prepend 540 * a page template to the front if it's set. 541 * 542 * @see https://buddypress.trac.wordpress.org/ticket/6065 543 * 544 * @since 2.2.0 545 * 546 * @param array $templates Array of templates. 547 * to use the defined page template for component's directory and its single items 548 * @return array 549 */ 550 public function theme_compat_page_templates( $templates = array() ) { 551 552 /** 553 * Filters whether or not we are looking at a directory to determine if to return early. 554 * 555 * @since 2.2.0 556 * 557 * @param bool $value Whether or not we are viewing a directory. 558 */ 559 if ( true === (bool) apply_filters( 'bp_legacy_theme_compat_page_templates_directory_only', ! bp_is_directory() ) ) { 560 return $templates; 561 } 562 563 // No page ID yet. 564 $page_id = 0; 565 566 // Get the WordPress Page ID for the current view. 567 foreach ( (array) buddypress()->pages as $component => $bp_page ) { 568 569 // Handles the majority of components. 570 if ( bp_is_current_component( $component ) ) { 571 $page_id = (int) $bp_page->id; 572 } 573 574 // Stop if not on a user page. 575 if ( ! bp_is_user() && ! empty( $page_id ) ) { 576 break; 577 } 578 579 // The Members component requires an explicit check due to overlapping components. 580 if ( bp_is_user() && ( 'members' === $component ) ) { 581 $page_id = (int) $bp_page->id; 582 break; 583 } 584 } 585 586 // Bail if no directory page set. 587 if ( 0 === $page_id ) { 588 return $templates; 589 } 590 591 // Check for page template. 592 $page_template = get_page_template_slug( $page_id ); 593 594 // Add it to the beginning of the templates array so it takes precedence 595 // over the default hierarchy. 596 if ( ! empty( $page_template ) ) { 597 598 /** 599 * Check for existence of template before adding it to template 600 * stack to avoid accidentally including an unintended file. 601 * 602 * @see: https://buddypress.trac.wordpress.org/ticket/6190 603 */ 604 if ( '' !== locate_template( $page_template ) ) { 605 array_unshift( $templates, $page_template ); 606 } 607 } 608 609 return $templates; 610 } 611 } 612 new BP_Legacy(); 613 endif; 614 615 /** 616 * Add the Create a Group button to the Groups directory title. 617 * 618 * The bp-legacy puts the Create a Group button into the page title, to mimic 619 * the behavior of bp-default. 620 * 621 * @since 2.0.0 622 * @todo Deprecate 623 * 624 * @param string $title Groups directory title. 625 * @return string 626 */ 627 function bp_legacy_theme_group_create_button( $title ) { 628 return $title . ' ' . bp_get_group_create_button(); 629 } 630 631 /** 632 * Add the Create a Group nav to the Groups directory navigation. 633 * 634 * The bp-legacy puts the Create a Group nav at the last position of 635 * the Groups directory navigation. 636 * 637 * @since 2.2.0 638 * 639 */ 640 function bp_legacy_theme_group_create_nav() { 641 bp_group_create_nav_item(); 642 } 643 644 /** 645 * Renders the group ID hidden input on group admin screens. 646 * 647 * @since 2.7.0 648 * 649 * @return string|null html 650 */ 651 function bp_legacy_groups_admin_screen_hidden_input() { 652 ?> 653 <input type="hidden" name="group-id" id="group-id" value="<?php bp_group_id(); ?>" /> 654 <?php 655 } 656 657 /** 658 * Add the Create a Site button to the Sites directory title. 659 * 660 * The bp-legacy puts the Create a Site button into the page title, to mimic 661 * the behavior of bp-default. 662 * 663 * @since 2.0.0 664 * @todo Deprecate 665 * 666 * @param string $title Sites directory title. 667 * @return string 668 */ 669 function bp_legacy_theme_blog_create_button( $title ) { 670 return $title . ' ' . bp_get_blog_create_button(); 671 } 672 673 /** 674 * Add the Create a Site nav to the Sites directory navigation. 675 * 676 * The bp-legacy puts the Create a Site nav at the last position of 677 * the Sites directory navigation. 678 * 679 * @since 2.2.0 680 * 681 */ 682 function bp_legacy_theme_blog_create_nav() { 683 bp_blog_create_nav_item(); 684 } 685 686 /** 687 * This function looks scarier than it actually is. :) 688 * Each object loop (activity/members/groups/blogs/forums) contains default 689 * parameters to show specific information based on the page we are currently 690 * looking at. 691 * 692 * The following function will take into account any cookies set in the JS and 693 * allow us to override the parameters sent. That way we can change the results 694 * returned without reloading the page. 695 * 696 * By using cookies we can also make sure that user settings are retained 697 * across page loads. 698 * 699 * @since 1.2.0 700 * 701 * @param string $query_string Query string for the current request. 702 * @param string $object Object for cookie. 703 * @return string Query string for the component loops. 704 */ 705 function bp_legacy_theme_ajax_querystring( $query_string, $object ) { 706 if ( empty( $object ) ) 707 return ''; 708 709 // Set up the cookies passed on this AJAX request. Store a local var to avoid conflicts. 710 if ( ! empty( $_POST['cookie'] ) ) { 711 $_BP_COOKIE = bp_parse_args( 712 str_replace( '; ', '&', urldecode( $_POST['cookie'] ) ) 713 ); 714 } else { 715 $_BP_COOKIE = &$_COOKIE; 716 } 717 718 $qs = array(); 719 720 /** 721 * Check if any cookie values are set. If there are then override the 722 * default params passed to the template loop. 723 */ 724 725 // Activity stream filtering on action. 726 if ( ! empty( $_BP_COOKIE['bp-' . $object . '-filter'] ) && '-1' != $_BP_COOKIE['bp-' . $object . '-filter'] ) { 727 $qs[] = 'type=' . urlencode( $_BP_COOKIE['bp-' . $object . '-filter'] ); 728 729 if ( bp_is_active( 'activity' ) ) { 730 $actions = bp_activity_get_actions_for_context(); 731 732 // Handle multiple actions (eg. 'friendship_accepted,friendship_created') 733 $action_filter = explode( ',', $_BP_COOKIE['bp-' . $object . '-filter'] ); 734 735 // See if action filter matches registered actions. If so, add it to qs. 736 if ( ! array_diff( $action_filter, wp_list_pluck( $actions, 'key' ) ) ) { 737 $qs[] = 'action=' . join( ',', $action_filter ); 738 } 739 } 740 } 741 742 if ( ! empty( $_BP_COOKIE['bp-' . $object . '-scope'] ) ) { 743 if ( 'personal' == $_BP_COOKIE['bp-' . $object . '-scope'] ) { 744 $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id(); 745 $qs[] = 'user_id=' . $user_id; 746 } 747 748 // Activity stream scope only on activity directory. 749 if ( 'all' != $_BP_COOKIE['bp-' . $object . '-scope'] && ! bp_displayed_user_id() && ! bp_is_single_item() ) 750 $qs[] = 'scope=' . urlencode( $_BP_COOKIE['bp-' . $object . '-scope'] ); 751 } 752 753 // If page and search_terms have been passed via the AJAX post request, use those. 754 if ( ! empty( $_POST['page'] ) && '-1' != $_POST['page'] ) 755 $qs[] = 'page=' . absint( $_POST['page'] ); 756 757 // Excludes activity just posted and avoids duplicate ids. 758 if ( ! empty( $_POST['exclude_just_posted'] ) ) { 759 $just_posted = wp_parse_id_list( $_POST['exclude_just_posted'] ); 760 $qs[] = 'exclude=' . implode( ',', $just_posted ); 761 } 762 763 // To get newest activities. 764 if ( ! empty( $_POST['offset'] ) ) { 765 $qs[] = 'offset=' . intval( $_POST['offset'] ); 766 } 767 768 $object_search_text = bp_get_search_default_text( $object ); 769 if ( ! empty( $_POST['search_terms'] ) && is_string( $_POST['search_terms'] ) && $object_search_text != $_POST['search_terms'] && 'false' != $_POST['search_terms'] && 'undefined' != $_POST['search_terms'] ) 770 $qs[] = 'search_terms=' . urlencode( $_POST['search_terms'] ); 771 772 // Now pass the querystring to override default values. 773 $query_string = empty( $qs ) ? '' : join( '&', (array) $qs ); 774 775 $object_filter = ''; 776 if ( isset( $_BP_COOKIE['bp-' . $object . '-filter'] ) ) 777 $object_filter = $_BP_COOKIE['bp-' . $object . '-filter']; 778 779 $object_scope = ''; 780 if ( isset( $_BP_COOKIE['bp-' . $object . '-scope'] ) ) 781 $object_scope = $_BP_COOKIE['bp-' . $object . '-scope']; 782 783 $object_page = ''; 784 if ( isset( $_BP_COOKIE['bp-' . $object . '-page'] ) ) 785 $object_page = $_BP_COOKIE['bp-' . $object . '-page']; 786 787 $object_search_terms = ''; 788 if ( isset( $_BP_COOKIE['bp-' . $object . '-search-terms'] ) ) 789 $object_search_terms = $_BP_COOKIE['bp-' . $object . '-search-terms']; 790 791 $object_extras = ''; 792 if ( isset( $_BP_COOKIE['bp-' . $object . '-extras'] ) ) 793 $object_extras = $_BP_COOKIE['bp-' . $object . '-extras']; 794 795 /** 796 * Filters the AJAX query string for the component loops. 797 * 798 * @since 1.7.0 799 * 800 * @param string $query_string The query string we are working with. 801 * @param string $object The type of page we are on. 802 * @param string $object_filter The current object filter. 803 * @param string $object_scope The current object scope. 804 * @param string $object_page The current object page. 805 * @param string $object_search_terms The current object search terms. 806 * @param string $object_extras The current object extras. 807 */ 808 return apply_filters( 'bp_legacy_theme_ajax_querystring', $query_string, $object, $object_filter, $object_scope, $object_page, $object_search_terms, $object_extras ); 809 } 810 811 /** 812 * Load the template loop for the current object. 813 * 814 * @since 1.2.0 815 * 816 * @return string|null Prints template loop for the specified object 817 */ 818 function bp_legacy_theme_object_template_loader() { 819 if ( ! bp_is_post_request() ) { 820 return; 821 } 822 823 // Bail if no object passed. 824 if ( empty( $_POST['object'] ) ) { 825 return; 826 } 827 828 // Sanitize the object. 829 $object = sanitize_title( $_POST['object'] ); 830 831 // Bail if object is not an active component to prevent arbitrary file inclusion. 832 if ( ! bp_is_active( $object ) ) { 833 return; 834 } 835 836 /** 837 * AJAX requests happen too early to be seen by bp_update_is_directory() 838 * so we do it manually here to ensure templates load with the correct 839 * context. Without this check, templates will load the 'single' version 840 * of themselves rather than the directory version. 841 */ 842 if ( ! bp_current_action() ) 843 bp_update_is_directory( true, bp_current_component() ); 844 845 // The template part can be overridden by the calling JS function. 846 if ( ! empty( $_POST['template'] ) && 'groups/single/members' === $_POST['template'] ) { 847 $template_part = 'groups/single/members.php'; 848 } else { 849 $template_part = $object . '/' . $object . '-loop.php'; 850 } 851 852 $template_path = bp_locate_template( array( $template_part ), false ); 853 854 $template_path = apply_filters( 'bp_legacy_object_template_path', $template_path ); 855 856 load_template( $template_path ); 857 exit(); 858 } 859 860 /** 861 * Load messages template loop when searched on the private message page 862 * 863 * @since 1.6.0 864 * 865 * @return string|null Prints template loop for the Messages component. 866 */ 867 function bp_legacy_theme_messages_template_loader() { 868 bp_get_template_part( 'members/single/messages/messages-loop' ); 869 exit(); 870 } 871 872 /** 873 * Load group invitations loop to handle pagination requests sent via AJAX. 874 * 875 * @since 2.0.0 876 */ 877 function bp_legacy_theme_invite_template_loader() { 878 bp_get_template_part( 'groups/single/invites-loop' ); 879 exit(); 880 } 881 882 /** 883 * Load group membership requests loop to handle pagination requests sent via AJAX. 884 * 885 * @since 2.0.0 886 */ 887 function bp_legacy_theme_requests_template_loader() { 888 bp_get_template_part( 'groups/single/requests-loop' ); 889 exit(); 890 } 891 892 /** 893 * Load the activity loop template when activity is requested via AJAX. 894 * 895 * @since 1.2.0 896 * 897 * @return string|null JSON object containing 'contents' (output of the template loop 898 * for the Activity component) and 'feed_url' (URL to the relevant RSS feed). 899 */ 900 function bp_legacy_theme_activity_template_loader() { 901 if ( ! bp_is_post_request() ) { 902 return; 903 } 904 905 $scope = ''; 906 if ( ! empty( $_POST['scope'] ) ) 907 $scope = $_POST['scope']; 908 909 // We need to calculate and return the feed URL for each scope. 910 switch ( $scope ) { 911 case 'friends': 912 $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/friends/feed/'; 913 break; 914 case 'groups': 915 $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/groups/feed/'; 916 break; 917 case 'favorites': 918 $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/favorites/feed/'; 919 break; 920 case 'mentions': 921 $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/feed/'; 922 923 if ( isset( $_POST['_wpnonce_activity_filter'] ) && wp_verify_nonce( wp_unslash( $_POST['_wpnonce_activity_filter'] ), 'activity_filter' ) ) { 924 bp_activity_clear_new_mentions( bp_loggedin_user_id() ); 925 } 926 927 break; 928 default: 929 $feed_url = home_url( bp_get_activity_root_slug() . '/feed/' ); 930 break; 931 } 932 933 // Buffer the loop in the template to a var for JS to spit out. 934 ob_start(); 935 bp_get_template_part( 'activity/activity-loop' ); 936 $result['contents'] = ob_get_contents(); 937 938 /** 939 * Filters the feed URL for when activity is requested via AJAX. 940 * 941 * @since 1.7.0 942 * 943 * @param string $feed_url URL for the feed to be used. 944 * @param string $scope Scope for the activity request. 945 */ 946 $result['feed_url'] = apply_filters( 'bp_legacy_theme_activity_feed_url', $feed_url, $scope ); 947 ob_end_clean(); 948 949 exit( json_encode( $result ) ); 950 } 951 952 /** 953 * Processes Activity updates received via a POST request. 954 * 955 * @since 1.2.0 956 * 957 * @return string|null HTML 958 */ 959 function bp_legacy_theme_post_update() { 960 $bp = buddypress(); 961 962 if ( ! bp_is_post_request() ) { 963 return; 964 } 965 966 // Check the nonce. 967 check_admin_referer( 'post_update', '_wpnonce_post_update' ); 968 969 if ( ! is_user_logged_in() ) 970 exit( '-1' ); 971 972 if ( empty( $_POST['content'] ) ) 973 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . __( 'Please enter some content to post.', 'buddypress' ) . '</p></div>' ); 974 975 $activity_id = 0; 976 $item_id = 0; 977 $object = ''; 978 979 980 // Try to get the item id from posted variables. 981 if ( ! empty( $_POST['item_id'] ) ) { 982 $item_id = (int) $_POST['item_id']; 983 } 984 985 // Try to get the object from posted variables. 986 if ( ! empty( $_POST['object'] ) ) { 987 $object = sanitize_key( $_POST['object'] ); 988 989 // If the object is not set and we're in a group, set the item id and the object 990 } elseif ( bp_is_group() ) { 991 $item_id = bp_get_current_group_id(); 992 $object = 'groups'; 993 } 994 995 if ( ! $object && bp_is_active( 'activity' ) ) { 996 $activity_id = bp_activity_post_update( array( 'content' => $_POST['content'], 'error_type' => 'wp_error' ) ); 997 998 } elseif ( 'groups' === $object ) { 999 if ( $item_id && bp_is_active( 'groups' ) ) 1000 $activity_id = groups_post_update( array( 'content' => $_POST['content'], 'group_id' => $item_id, 'error_type' => 'wp_error' ) ); 1001 1002 } else { 1003 1004 /** This filter is documented in bp-activity/actions/post.php */ 1005 $activity_id = apply_filters( 'bp_activity_custom_update', false, $object, $item_id, $_POST['content'] ); 1006 } 1007 1008 if ( false === $activity_id ) { 1009 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . __( 'There was a problem posting your update. Please try again.', 'buddypress' ) . '</p></div>' ); 1010 } elseif ( is_wp_error( $activity_id ) && $activity_id->get_error_code() ) { 1011 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . $activity_id->get_error_message() . '</p></div>' ); 1012 } 1013 1014 $last_recorded = ! empty( $_POST['since'] ) ? date( 'Y-m-d H:i:s', intval( $_POST['since'] ) ) : 0; 1015 if ( $last_recorded ) { 1016 $activity_args = array( 'since' => $last_recorded ); 1017 $bp->activity->last_recorded = $last_recorded; 1018 add_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10, 1 ); 1019 } else { 1020 $activity_args = array( 'include' => $activity_id ); 1021 } 1022 1023 if ( bp_has_activities ( $activity_args ) ) { 1024 while ( bp_activities() ) { 1025 bp_the_activity(); 1026 bp_get_template_part( 'activity/entry' ); 1027 } 1028 } 1029 1030 if ( ! empty( $last_recorded ) ) { 1031 remove_filter( 'bp_get_activity_css_class', 'bp_activity_newest_class', 10 ); 1032 } 1033 1034 exit; 1035 } 1036 1037 /** 1038 * Posts new Activity comments received via a POST request. 1039 * 1040 * @since 1.2.0 1041 * 1042 * @global BP_Activity_Template $activities_template 1043 * 1044 * @return string|null HTML 1045 */ 1046 function bp_legacy_theme_new_activity_comment() { 1047 global $activities_template; 1048 1049 $bp = buddypress(); 1050 1051 if ( ! bp_is_post_request() ) { 1052 return; 1053 } 1054 1055 // Check the nonce. 1056 check_admin_referer( 'new_activity_comment', '_wpnonce_new_activity_comment' ); 1057 1058 if ( ! is_user_logged_in() ) { 1059 exit( '-1' ); 1060 } 1061 1062 $feedback = __( 'There was an error posting your reply. Please try again.', 'buddypress' ); 1063 1064 if ( empty( $_POST['content'] ) ) { 1065 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . esc_html__( 'Please do not leave the comment area blank.', 'buddypress' ) . '</p></div>' ); 1066 } 1067 1068 if ( empty( $_POST['form_id'] ) || empty( $_POST['comment_id'] ) || ! is_numeric( $_POST['form_id'] ) || ! is_numeric( $_POST['comment_id'] ) ) { 1069 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . esc_html( $feedback ) . '</p></div>' ); 1070 } 1071 1072 $activity_id = (int) $_POST['form_id']; 1073 $activity_item = new BP_Activity_Activity( $activity_id ); 1074 if ( ! bp_activity_user_can_read( $activity_item ) ) { 1075 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . esc_html( $feedback ) . '</p></div>' ); 1076 } 1077 1078 $comment_id = bp_activity_new_comment( array( 1079 'activity_id' => $activity_id, 1080 'content' => $_POST['content'], 1081 'parent_id' => $_POST['comment_id'], 1082 'error_type' => 'wp_error' 1083 ) ); 1084 1085 if ( is_wp_error( $comment_id ) ) { 1086 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . esc_html( $comment_id->get_error_message() ) . '</p></div>' ); 1087 } 1088 1089 // Load the new activity item into the $activities_template global. 1090 bp_has_activities( 'display_comments=stream&hide_spam=false&show_hidden=true&include=' . $comment_id ); 1091 1092 // Swap the current comment with the activity item we just loaded. 1093 if ( isset( $activities_template->activities[0] ) ) { 1094 $activities_template->activity = new stdClass(); 1095 $activities_template->activity->id = $activities_template->activities[0]->item_id; 1096 $activities_template->activity->current_comment = $activities_template->activities[0]; 1097 1098 // Because the whole tree has not been loaded, we manually 1099 // determine depth. 1100 $depth = 1; 1101 $parent_id = (int) $activities_template->activities[0]->secondary_item_id; 1102 while ( $parent_id !== (int) $activities_template->activities[0]->item_id ) { 1103 $depth++; 1104 $p_obj = new BP_Activity_Activity( $parent_id ); 1105 $parent_id = (int) $p_obj->secondary_item_id; 1106 } 1107 $activities_template->activity->current_comment->depth = $depth; 1108 } 1109 1110 // Get activity comment template part. 1111 bp_get_template_part( 'activity/comment' ); 1112 1113 unset( $activities_template ); 1114 exit; 1115 } 1116 1117 /** 1118 * Deletes an Activity item received via a POST request. 1119 * 1120 * @since 1.2.0 1121 * 1122 * @return mixed String on error, void on success. 1123 */ 1124 function bp_legacy_theme_delete_activity() { 1125 if ( ! bp_is_post_request() ) { 1126 return; 1127 } 1128 1129 // Check the nonce. 1130 check_admin_referer( 'bp_activity_delete_link' ); 1131 1132 if ( ! is_user_logged_in() ) 1133 exit( '-1' ); 1134 1135 if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 1136 exit( '-1' ); 1137 1138 $activity = new BP_Activity_Activity( (int) $_POST['id'] ); 1139 1140 // Check access. 1141 if ( ! bp_activity_user_can_delete( $activity ) ) 1142 exit( '-1' ); 1143 1144 /** This action is documented in bp-activity/bp-activity-actions.php */ 1145 do_action( 'bp_activity_before_action_delete_activity', $activity->id, $activity->user_id ); 1146 1147 if ( ! bp_activity_delete( array( 'id' => $activity->id, 'user_id' => $activity->user_id ) ) ) 1148 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . __( 'There was a problem when deleting. Please try again.', 'buddypress' ) . '</p></div>' ); 1149 1150 /** This action is documented in bp-activity/bp-activity-actions.php */ 1151 do_action( 'bp_activity_action_delete_activity', $activity->id, $activity->user_id ); 1152 exit; 1153 } 1154 1155 /** 1156 * Deletes an Activity comment received via a POST request. 1157 * 1158 * @since 1.2.0 1159 * 1160 * @return mixed String on error, void on success. 1161 */ 1162 function bp_legacy_theme_delete_activity_comment() { 1163 if ( ! bp_is_post_request() ) { 1164 return; 1165 } 1166 1167 // Check the nonce. 1168 check_admin_referer( 'bp_activity_delete_link' ); 1169 1170 if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) { 1171 exit( '-1' ); 1172 } 1173 1174 if ( ! is_user_logged_in() ) { 1175 exit( '-1' ); 1176 } 1177 1178 $comment = new BP_Activity_Activity( $_POST['id'] ); 1179 1180 // Check access. 1181 if ( ! bp_current_user_can( 'bp_moderate' ) && $comment->user_id != bp_loggedin_user_id() ) 1182 exit( '-1' ); 1183 1184 /** This action is documented in bp-activity/bp-activity-actions.php */ 1185 do_action( 'bp_activity_before_action_delete_activity', $_POST['id'], $comment->user_id ); 1186 1187 if ( ! bp_activity_delete_comment( $comment->item_id, $comment->id ) ) 1188 exit( '-1<div id="message" class="error bp-ajax-message"><p>' . __( 'There was a problem when deleting. Please try again.', 'buddypress' ) . '</p></div>' ); 1189 1190 /** This action is documented in bp-activity/bp-activity-actions.php */ 1191 do_action( 'bp_activity_action_delete_activity', $_POST['id'], $comment->user_id ); 1192 exit; 1193 } 1194 1195 /** 1196 * AJAX spam an activity item or comment. 1197 * 1198 * @since 1.6.0 1199 * 1200 * @return mixed String on error, void on success. 1201 */ 1202 function bp_legacy_theme_spam_activity() { 1203 $bp = buddypress(); 1204 1205 if ( ! bp_is_post_request() ) { 1206 return; 1207 } 1208 1209 // Check that user is logged in, Activity Streams are enabled, and Akismet is present. 1210 if ( ! is_user_logged_in() || ! bp_is_active( 'activity' ) || empty( $bp->activity->akismet ) ) 1211 exit( '-1' ); 1212 1213 // Check an item ID was passed. 1214 if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 1215 exit( '-1' ); 1216 1217 // Is the current user allowed to spam items? 1218 if ( ! bp_activity_user_can_mark_spam() ) 1219 exit( '-1' ); 1220 1221 // Load up the activity item. 1222 $activity = new BP_Activity_Activity( (int) $_POST['id'] ); 1223 if ( empty( $activity->component ) ) 1224 exit( '-1' ); 1225 1226 // Check nonce. 1227 check_admin_referer( 'bp_activity_akismet_spam_' . $activity->id ); 1228 1229 /** This action is documented in bp-activity/bp-activity-actions.php */ 1230 do_action( 'bp_activity_before_action_spam_activity', $activity->id, $activity ); 1231 1232 // Mark as spam. 1233 bp_activity_mark_as_spam( $activity ); 1234 $activity->save(); 1235 1236 /** This action is documented in bp-activity/bp-activity-actions.php */ 1237 do_action( 'bp_activity_action_spam_activity', $activity->id, $activity->user_id ); 1238 exit; 1239 } 1240 1241 /** 1242 * Mark an activity as a favourite via a POST request. 1243 * 1244 * @since 1.2.0 1245 * 1246 * @return string|null HTML 1247 */ 1248 function bp_legacy_theme_mark_activity_favorite() { 1249 // Bail if not a POST action. 1250 if ( ! bp_is_post_request() ) { 1251 return; 1252 } 1253 1254 if ( ! isset( $_POST['nonce'] ) ) { 1255 return; 1256 } 1257 1258 // Either the 'mark' or 'unmark' nonce is accepted, for backward compatibility. 1259 $nonce = wp_unslash( $_POST['nonce'] ); 1260 if ( ! wp_verify_nonce( $nonce, 'mark_favorite' ) && ! wp_verify_nonce( $nonce, 'unmark_favorite' ) ) { 1261 return; 1262 } 1263 1264 $activity_id = (int) $_POST['id']; 1265 $activity_item = new BP_Activity_Activity( $activity_id ); 1266 if ( ! bp_activity_user_can_read( $activity_item, bp_loggedin_user_id() ) ) { 1267 return; 1268 } 1269 1270 if ( bp_activity_add_user_favorite( $_POST['id'] ) ) 1271 _e( 'Remove Favorite', 'buddypress' ); 1272 else 1273 _e( 'Favorite', 'buddypress' ); 1274 1275 exit; 1276 } 1277 1278 /** 1279 * Un-favourite an activity via a POST request. 1280 * 1281 * @since 1.2.0 1282 * 1283 * @return string|null HTML 1284 */ 1285 function bp_legacy_theme_unmark_activity_favorite() { 1286 if ( ! bp_is_post_request() ) { 1287 return; 1288 } 1289 1290 if ( ! isset( $_POST['nonce'] ) ) { 1291 return; 1292 } 1293 1294 // Either the 'mark' or 'unmark' nonce is accepted, for backward compatibility. 1295 $nonce = wp_unslash( $_POST['nonce'] ); 1296 if ( ! wp_verify_nonce( $nonce, 'mark_favorite' ) && ! wp_verify_nonce( $nonce, 'unmark_favorite' ) ) { 1297 return; 1298 } 1299 1300 if ( bp_activity_remove_user_favorite( $_POST['id'] ) ) 1301 _e( 'Favorite', 'buddypress' ); 1302 else 1303 _e( 'Remove Favorite', 'buddypress' ); 1304 1305 exit; 1306 } 1307 1308 /** 1309 * Fetches an activity's full, non-excerpted content via a POST request. 1310 * Used for the 'Read More' link on long activity items. 1311 * 1312 * @since 1.5.0 1313 * 1314 * @return string|null HTML 1315 */ 1316 function bp_legacy_theme_get_single_activity_content() { 1317 if ( ! bp_is_post_request() ) { 1318 return; 1319 } 1320 1321 $activity_array = bp_activity_get_specific( array( 1322 'activity_ids' => $_POST['activity_id'], 1323 'display_comments' => 'stream' 1324 ) ); 1325 1326 $activity = ! empty( $activity_array['activities'][0] ) ? $activity_array['activities'][0] : false; 1327 1328 if ( empty( $activity ) ) 1329 exit; // @todo: error? 1330 1331 /** 1332 * Fires before the return of an activity's full, non-excerpted content via a POST request. 1333 * 1334 * @since 1.7.0 1335 * 1336 * @param string $activity Activity content. Passed by reference. 1337 */ 1338 do_action_ref_array( 'bp_legacy_theme_get_single_activity_content', array( &$activity ) ); 1339 1340 // Activity content retrieved through AJAX should run through normal filters, but not be truncated. 1341 remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 ); 1342 1343 /** This filter is documented in bp-activity/bp-activity-template.php */ 1344 $content = apply_filters_ref_array( 'bp_get_activity_content_body', array( $activity->content, &$activity ) ); 1345 1346 exit( $content ); 1347 } 1348 1349 /** 1350 * Invites a friend to join a group via a POST request. 1351 * 1352 * @since 1.2.0 1353 * 1354 * @todo Audit return types 1355 */ 1356 function bp_legacy_theme_ajax_invite_user() { 1357 if ( ! bp_is_post_request() ) { 1358 return; 1359 } 1360 1361 check_ajax_referer( 'groups_invite_uninvite_user' ); 1362 1363 if ( ! $_POST['friend_id'] || ! $_POST['friend_action'] || ! $_POST['group_id'] ) 1364 return; 1365 1366 if ( ! bp_groups_user_can_send_invites( $_POST['group_id'] ) ) 1367 return; 1368 1369 $group_id = (int) $_POST['group_id']; 1370 $friend_id = (int) $_POST['friend_id']; 1371 1372 if ( 'invite' == $_POST['friend_action'] ) { 1373 if ( ! friends_check_friendship( bp_loggedin_user_id(), $_POST['friend_id'] ) ) { 1374 return; 1375 } 1376 1377 $group = groups_get_group( $group_id ); 1378 1379 // Users who have previously requested membership do not need 1380 // another invitation created for them. 1381 if ( groups_check_for_membership_request( $friend_id, $group_id ) ) { 1382 $user_status = 'is_pending'; 1383 1384 // Create the user invitation. 1385 } elseif ( groups_invite_user( array( 'user_id' => $friend_id, 'group_id' => $group_id ) ) ) { 1386 $user_status = 'is_invited'; 1387 1388 // Miscellaneous failure. 1389 } else { 1390 return; 1391 } 1392 1393 $user = new BP_Core_User( $friend_id ); 1394 1395 $uninvite_url = bp_is_current_action( 'create' ) 1396 ? bp_get_groups_directory_permalink() . 'create/step/group-invites/?user_id=' . $friend_id 1397 : bp_get_group_permalink( $group ) . 'send-invites/remove/' . $friend_id; 1398 1399 echo '<li id="uid-' . esc_attr( $user->id ) . '">'; 1400 echo $user->avatar_thumb; 1401 echo '<h4>' . $user->user_link . '</h4>'; 1402 echo '<span class="activity">' . esc_attr( $user->last_active ) . '</span>'; 1403 echo '<div class="action"> 1404 <a class="button remove" href="' . wp_nonce_url( $uninvite_url, 'groups_invite_uninvite_user' ) . '" id="uid-' . esc_attr( $user->id ) . '">' . __( 'Remove Invite', 'buddypress' ) . '</a> 1405 </div>'; 1406 1407 if ( 'is_pending' == $user_status ) { 1408 /* translators: %s: user link */ 1409 echo '<p class="description">' . sprintf( __( '%s has previously requested to join this group. Sending an invitation will automatically add the member to the group.', 'buddypress' ), $user->user_link ) . '</p>'; 1410 } 1411 1412 echo '</li>'; 1413 exit; 1414 1415 } elseif ( 'uninvite' == $_POST['friend_action'] ) { 1416 // Users who have previously requested membership should not 1417 // have their requests deleted on the "uninvite" action. 1418 if ( BP_Groups_Member::check_for_membership_request( $friend_id, $group_id ) ) { 1419 return; 1420 } 1421 1422 // Remove the unsent invitation. 1423 if ( ! groups_uninvite_user( $friend_id, $group_id ) ) { 1424 return; 1425 } 1426 1427 exit; 1428 1429 } else { 1430 return; 1431 } 1432 } 1433 1434 /** 1435 * Friend/un-friend a user via a POST request. 1436 * 1437 * @since 1.2.0 1438 * 1439 * @return string|null HTML 1440 */ 1441 function bp_legacy_theme_ajax_addremove_friend() { 1442 if ( ! bp_is_post_request() ) { 1443 return; 1444 } 1445 1446 // Cast fid as an integer. 1447 $friend_id = (int) $_POST['fid']; 1448 1449 $user = get_user_by( 'id', $friend_id ); 1450 if ( ! $user ) { 1451 die( __( 'No member found by that ID.', 'buddypress' ) ); 1452 } 1453 1454 // Trying to cancel friendship. 1455 if ( 'is_friend' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 1456 check_ajax_referer( 'friends_remove_friend' ); 1457 1458 if ( ! friends_remove_friend( bp_loggedin_user_id(), $friend_id ) ) { 1459 echo __( 'Friendship could not be canceled.', 'buddypress' ); 1460 } else { 1461 echo '<a id="friend-' . esc_attr( $friend_id ) . '" class="friendship-button not_friends add" rel="add" href="' . wp_nonce_url( bp_loggedin_user_domain() . bp_get_friends_slug() . '/add-friend/' . $friend_id, 'friends_add_friend' ) . '">' . __( 'Add Friend', 'buddypress' ) . '</a>'; 1462 } 1463 1464 // Trying to request friendship. 1465 } elseif ( 'not_friends' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 1466 check_ajax_referer( 'friends_add_friend' ); 1467 1468 if ( ! friends_add_friend( bp_loggedin_user_id(), $friend_id ) ) { 1469 echo __(' Friendship could not be requested.', 'buddypress' ); 1470 } else { 1471 echo '<a id="friend-' . esc_attr( $friend_id ) . '" class="remove friendship-button pending_friend requested" rel="remove" href="' . wp_nonce_url( bp_loggedin_user_domain() . bp_get_friends_slug() . '/requests/cancel/' . $friend_id . '/', 'friends_withdraw_friendship' ) . '" class="requested">' . __( 'Cancel Friendship Request', 'buddypress' ) . '</a>'; 1472 } 1473 1474 // Trying to cancel pending request. 1475 } elseif ( 'pending' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 1476 check_ajax_referer( 'friends_withdraw_friendship' ); 1477 1478 if ( friends_withdraw_friendship( bp_loggedin_user_id(), $friend_id ) ) { 1479 echo '<a id="friend-' . esc_attr( $friend_id ) . '" class="friendship-button not_friends add" rel="add" href="' . wp_nonce_url( bp_loggedin_user_domain() . bp_get_friends_slug() . '/add-friend/' . $friend_id, 'friends_add_friend' ) . '">' . __( 'Add Friend', 'buddypress' ) . '</a>'; 1480 } else { 1481 echo __("Friendship request could not be cancelled.", 'buddypress'); 1482 } 1483 1484 // Request already pending. 1485 } else { 1486 echo __( 'Request Pending', 'buddypress' ); 1487 } 1488 1489 exit; 1490 } 1491 1492 /** 1493 * Accept a user friendship request via a POST request. 1494 * 1495 * @since 1.2.0 1496 * 1497 * @return mixed String on error, void on success. 1498 */ 1499 function bp_legacy_theme_ajax_accept_friendship() { 1500 if ( ! bp_is_post_request() ) { 1501 return; 1502 } 1503 1504 check_admin_referer( 'friends_accept_friendship' ); 1505 1506 if ( ! friends_accept_friendship( (int) $_POST['id'] ) ) 1507 echo "-1<div id='message' class='error'><p>" . __( 'There was a problem accepting that request. Please try again.', 'buddypress' ) . '</p></div>'; 1508 1509 exit; 1510 } 1511 1512 /** 1513 * Reject a user friendship request via a POST request. 1514 * 1515 * @since 1.2.0 1516 * 1517 * @return mixed String on error, void on success. 1518 */ 1519 function bp_legacy_theme_ajax_reject_friendship() { 1520 if ( ! bp_is_post_request() ) { 1521 return; 1522 } 1523 1524 check_admin_referer( 'friends_reject_friendship' ); 1525 1526 if ( ! friends_reject_friendship( (int) $_POST['id'] ) ) 1527 echo "-1<div id='message' class='error'><p>" . __( 'There was a problem rejecting that request. Please try again.', 'buddypress' ) . '</p></div>'; 1528 1529 exit; 1530 } 1531 1532 /** 1533 * Join or leave a group when clicking the "join/leave" button via a POST request. 1534 * 1535 * @since 1.2.0 1536 * 1537 * @return string|null HTML 1538 */ 1539 function bp_legacy_theme_ajax_joinleave_group() { 1540 if ( ! bp_is_post_request() ) { 1541 return; 1542 } 1543 1544 // Cast gid as integer. 1545 $group_id = (int) $_POST['gid']; 1546 1547 if ( groups_is_user_banned( bp_loggedin_user_id(), $group_id ) ) { 1548 return; 1549 } 1550 1551 $group = groups_get_group( $group_id ); 1552 1553 if ( ! $group ) { 1554 return; 1555 } 1556 1557 $action = ''; 1558 if ( isset( $_POST['action'] ) ) { 1559 $action = sanitize_key( wp_unslash( $_POST['action'] ) ); 1560 } 1561 1562 // Client doesn't distinguish between different request types, so we infer from user status. 1563 if ( groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) { 1564 $request_type = 'leave_group'; 1565 } elseif ( groups_check_user_has_invite( bp_loggedin_user_id(), $group->id ) && 'joinleave_group' !== $action ) { 1566 $request_type = 'accept_invite'; 1567 } elseif ( 'private' === $group->status ) { 1568 $request_type = 'request_membership'; 1569 } else { 1570 $request_type = 'join_group'; 1571 } 1572 1573 switch ( $request_type ) { 1574 case 'join_group' : 1575 if ( ! bp_current_user_can( 'groups_join_group', array( 'group_id' => $group->id ) ) ) { 1576 esc_html_e( 'Error joining group', 'buddypress' ); 1577 } 1578 1579 check_ajax_referer( 'groups_join_group' ); 1580 1581 if ( ! groups_join_group( $group->id ) ) { 1582 _e( 'Error joining group', 'buddypress' ); 1583 } else { 1584 echo '<a id="group-' . esc_attr( $group->id ) . '" class="group-button leave-group" rel="leave" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'leave-group', 'groups_leave_group' ) . '">' . __( 'Leave Group', 'buddypress' ) . '</a>'; 1585 } 1586 break; 1587 1588 case 'accept_invite' : 1589 if ( ! bp_current_user_can( 'groups_request_membership', array( 'group_id' => $group->id ) ) ) { 1590 esc_html_e( 'Error accepting invitation', 'buddypress' ); 1591 } 1592 1593 check_ajax_referer( 'groups_accept_invite' ); 1594 1595 if ( ! groups_accept_invite( bp_loggedin_user_id(), $group->id ) ) { 1596 _e( 'Error requesting membership', 'buddypress' ); 1597 } else { 1598 echo '<a id="group-' . esc_attr( $group->id ) . '" class="group-button leave-group" rel="leave" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'leave-group', 'groups_leave_group' ) . '">' . __( 'Leave Group', 'buddypress' ) . '</a>'; 1599 } 1600 break; 1601 1602 case 'request_membership' : 1603 check_ajax_referer( 'groups_request_membership' ); 1604 1605 if ( ! groups_send_membership_request( [ 'user_id' => bp_loggedin_user_id(), 'group_id' => $group->id ] ) ) { 1606 _e( 'Error requesting membership', 'buddypress' ); 1607 } else { 1608 echo '<a id="group-' . esc_attr( $group->id ) . '" class="group-button disabled pending membership-requested" rel="membership-requested" href="' . bp_get_group_permalink( $group ) . '">' . __( 'Request Sent', 'buddypress' ) . '</a>'; 1609 } 1610 break; 1611 1612 case 'leave_group' : 1613 check_ajax_referer( 'groups_leave_group' ); 1614 1615 if ( ! groups_leave_group( $group->id ) ) { 1616 _e( 'Error leaving group', 'buddypress' ); 1617 } elseif ( 'public' === $group->status ) { 1618 echo '<a id="group-' . esc_attr( $group->id ) . '" class="group-button join-group" rel="join" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'join', 'groups_join_group' ) . '">' . __( 'Join Group', 'buddypress' ) . '</a>'; 1619 } else { 1620 echo '<a id="group-' . esc_attr( $group->id ) . '" class="group-button request-membership" rel="join" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'request-membership', 'groups_request_membership' ) . '">' . __( 'Request Membership', 'buddypress' ) . '</a>'; 1621 } 1622 break; 1623 } 1624 1625 exit; 1626 } 1627 1628 /** 1629 * Close and keep closed site wide notices from an admin in the sidebar, via a POST request. 1630 * 1631 * @since 1.2.0 1632 * 1633 * @return mixed String on error, void on success. 1634 */ 1635 function bp_legacy_theme_ajax_close_notice() { 1636 if ( ! bp_is_post_request() ) { 1637 return; 1638 } 1639 1640 $nonce_check = isset( $_POST['nonce'] ) && wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'bp_messages_close_notice' ); 1641 1642 if ( ! $nonce_check || ! isset( $_POST['notice_id'] ) ) { 1643 echo "-1<div id='message' class='error'><p>" . __( 'There was a problem closing the notice.', 'buddypress' ) . '</p></div>'; 1644 1645 } else { 1646 bp_messages_dismiss_sitewide_notice( bp_loggedin_user_id(), (int) $_POST['notice_id'] ); 1647 } 1648 1649 exit; 1650 } 1651 1652 /** 1653 * Send a private message reply to a thread via a POST request. 1654 * 1655 * @since 1.2.0 1656 * 1657 * @return string|null HTML 1658 */ 1659 function bp_legacy_theme_ajax_messages_send_reply() { 1660 if ( ! bp_is_post_request() ) { 1661 return; 1662 } 1663 1664 check_ajax_referer( 'messages_send_message' ); 1665 1666 $thread_id = (int) $_POST['thread_id']; 1667 1668 // Cannot respond to a thread you're not already a recipient on. 1669 if ( ! bp_current_user_can( 'bp_moderate' ) && ( ! messages_is_valid_thread( $thread_id ) || ! messages_check_thread_access( $thread_id ) ) ) { 1670 echo "-1<div id='message' class='error'><p>" . __( 'There was a problem sending that reply. Please try again.', 'buddypress' ) . '</p></div>'; 1671 die; 1672 } 1673 1674 $result = messages_new_message( array( 'thread_id' => $thread_id, 'content' => $_REQUEST['content'] ) ); 1675 1676 if ( !empty( $result ) ) { 1677 1678 // Pretend we're in the message loop. 1679 global $thread_template; 1680 1681 bp_thread_has_messages( array( 'thread_id' => $thread_id ) ); 1682 1683 // Set the current message to the 2nd last. 1684 $thread_template->message = end( $thread_template->thread->messages ); 1685 $thread_template->message = prev( $thread_template->thread->messages ); 1686 1687 // Set current message to current key. 1688 $thread_template->current_message = key( $thread_template->thread->messages ); 1689 1690 // Now manually iterate message like we're in the loop. 1691 bp_thread_the_message(); 1692 1693 // Manually call oEmbed 1694 // this is needed because we're not at the beginning of the loop. 1695 bp_messages_embed(); 1696 1697 // Add new-message css class. 1698 add_filter( 'bp_get_the_thread_message_css_class', function( $retval ) { 1699 $retval[] = 'new-message'; 1700 return $retval; 1701 } ); 1702 1703 // Output single message template part. 1704 bp_get_template_part( 'members/single/messages/message' ); 1705 1706 // Clean up the loop. 1707 bp_thread_messages(); 1708 1709 } else { 1710 echo "-1<div id='message' class='error'><p>" . __( 'There was a problem sending that reply. Please try again.', 'buddypress' ) . '</p></div>'; 1711 } 1712 1713 exit; 1714 } 1715 1716 /** 1717 * Mark a private message as unread in your inbox via a POST request. 1718 * 1719 * No longer used. 1720 * 1721 * @since 1.2.0 1722 * @deprecated 2.2.0 1723 * 1724 * @return mixed String on error, void on success. 1725 */ 1726 function bp_legacy_theme_ajax_message_markunread() { 1727 die( '-1' ); 1728 } 1729 1730 /** 1731 * Mark a private message as read in your inbox via a POST request. 1732 * 1733 * No longer used. 1734 * 1735 * @since 1.2.0 1736 * @deprecated 2.2.0 1737 * 1738 * @return mixed String on error, void on success. 1739 */ 1740 function bp_legacy_theme_ajax_message_markread() { 1741 die( '-1' ); 1742 } 1743 1744 /** 1745 * Delete a private message(s) in your inbox via a POST request. 1746 * 1747 * No longer used. 1748 * 1749 * @since 1.2.0 1750 * @deprecated 2.2.0 1751 * 1752 * @return string|null HTML 1753 */ 1754 function bp_legacy_theme_ajax_messages_delete() { 1755 die( '-1' ); 1756 } 1757 1758 /** 1759 * AJAX handler for autocomplete. 1760 * 1761 * Displays friends only, unless BP_MESSAGES_AUTOCOMPLETE_ALL is defined. 1762 * 1763 * @since 1.2.0 1764 */ 1765 function bp_legacy_theme_ajax_messages_autocomplete_results() { 1766 1767 /** 1768 * Filters the max results default value for ajax messages autocomplete results. 1769 * 1770 * @since 1.5.0 1771 * 1772 * @param int $value Max results for autocomplete. Default 10. 1773 */ 1774 $limit = isset( $_GET['limit'] ) ? absint( $_GET['limit'] ) : (int) apply_filters( 'bp_autocomplete_max_results', 10 ); 1775 $term = isset( $_GET['q'] ) ? sanitize_text_field( $_GET['q'] ) : ''; 1776 1777 // Include everyone in the autocomplete, or just friends? 1778 if ( bp_is_current_component( bp_get_messages_slug() ) ) { 1779 $only_friends = ( buddypress()->messages->autocomplete_all === false ); 1780 } else { 1781 $only_friends = true; 1782 } 1783 1784 $suggestions = bp_core_get_suggestions( array( 1785 'limit' => $limit, 1786 'only_friends' => $only_friends, 1787 'term' => $term, 1788 'type' => 'members', 1789 ) ); 1790 1791 if ( $suggestions && ! is_wp_error( $suggestions ) ) { 1792 foreach ( $suggestions as $user ) { 1793 1794 // Note that the final line break acts as a delimiter for the 1795 // autocomplete JavaScript and thus should not be removed. 1796 printf( '<span id="%s" href="#"></span><img src="%s" style="width: 15px"> %s (%s)' . "\n", 1797 esc_attr( 'link-' . $user->ID ), 1798 esc_url( $user->image ), 1799 esc_html( $user->name ), 1800 esc_html( $user->ID ) 1801 ); 1802 } 1803 } 1804 1805 exit; 1806 } 1807 1808 /** 1809 * AJAX callback to set a message's star status. 1810 * 1811 * @since 2.3.0 1812 */ 1813 function bp_legacy_theme_ajax_messages_star_handler() { 1814 if ( false === bp_is_active( 'messages', 'star' ) || empty( $_POST['message_id'] ) ) { 1815 return; 1816 } 1817 1818 // Check nonce. 1819 check_ajax_referer( 'bp-messages-star-' . (int) $_POST['message_id'], 'nonce' ); 1820 1821 // Check capability. 1822 if ( ! is_user_logged_in() || ! bp_core_can_edit_settings() ) { 1823 return; 1824 } 1825 1826 if ( true === bp_messages_star_set_action( array( 1827 'action' => $_POST['star_status'], 1828 'message_id' => (int) $_POST['message_id'], 1829 'bulk' => ! empty( $_POST['bulk'] ) ? true : false 1830 ) ) ) { 1831 echo '1'; 1832 die(); 1833 } 1834 1835 echo '-1'; 1836 die(); 1837 } 1838 1839 /** 1840 * BP Legacy's callback for the cover image feature. 1841 * 1842 * @since 2.4.0 1843 * 1844 * @param array $params the current component's feature parameters. 1845 * @return null|string An array to inform about the css handle to attach the css rules to 1846 */ 1847 function bp_legacy_theme_cover_image( $params = array() ) { 1848 if ( empty( $params ) ) { 1849 return; 1850 } 1851 1852 // Avatar height - padding - 1/2 avatar height. 1853 $avatar_offset = $params['height'] - 5 - round( (int) bp_core_avatar_full_height() / 2 ); 1854 1855 // Header content offset + spacing. 1856 $top_offset = bp_core_avatar_full_height() - 10; 1857 $left_offset = bp_core_avatar_full_width() + 20; 1858 1859 $cover_image = ( !empty( $params['cover_image'] ) ) ? 'background-image: url(' . $params['cover_image'] . ');' : ''; 1860 1861 $hide_avatar_style = ''; 1862 1863 // Adjust the cover image header, in case avatars are completely disabled. 1864 if ( ! buddypress()->avatar->show_avatars ) { 1865 $hide_avatar_style = ' 1866 #buddypress #item-header-cover-image #item-header-avatar { 1867 display: none; 1868 } 1869 '; 1870 1871 if ( bp_is_user() ) { 1872 $hide_avatar_style = ' 1873 #buddypress #item-header-cover-image #item-header-avatar a { 1874 display: block; 1875 height: ' . $top_offset . 'px; 1876 margin: 0 15px 19px 0; 1877 } 1878 1879 #buddypress div#item-header #item-header-cover-image #item-header-content { 1880 margin-left: auto; 1881 } 1882 '; 1883 } 1884 } 1885 1886 return ' 1887 /* Cover image */ 1888 #buddypress #header-cover-image { 1889 height: ' . $params["height"] . 'px; 1890 ' . $cover_image . ' 1891 } 1892 1893 #buddypress #create-group-form #header-cover-image { 1894 margin: 1em 0; 1895 position: relative; 1896 } 1897 1898 .bp-user #buddypress #item-header { 1899 padding-top: 0; 1900 } 1901 1902 #buddypress #item-header-cover-image #item-header-avatar { 1903 margin-top: '. $avatar_offset .'px; 1904 float: left; 1905 overflow: visible; 1906 width: auto; 1907 } 1908 1909 #buddypress div#item-header #item-header-cover-image #item-header-content { 1910 clear: both; 1911 float: left; 1912 margin-left: ' . $left_offset . 'px; 1913 margin-top: -' . $top_offset . 'px; 1914 width: auto; 1915 } 1916 1917 body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-header-content, 1918 body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions { 1919 clear: none; 1920 margin-top: ' . $params["height"] . 'px; 1921 margin-left: 0; 1922 max-width: 50%; 1923 } 1924 1925 body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions { 1926 max-width: 20%; 1927 padding-top: 20px; 1928 } 1929 1930 ' . $hide_avatar_style . ' 1931 1932 #buddypress div#item-header-cover-image .user-nicename a, 1933 #buddypress div#item-header-cover-image .user-nicename { 1934 font-size: 200%; 1935 color: #fff; 1936 margin: 0 0 0.6em; 1937 text-rendering: optimizelegibility; 1938 text-shadow: 0 0 3px rgba( 0, 0, 0, 0.8 ); 1939 } 1940 1941 #buddypress #item-header-cover-image #item-header-avatar img.avatar { 1942 background: rgba( 255, 255, 255, 0.8 ); 1943 border: solid 2px #fff; 1944 } 1945 1946 #buddypress #item-header-cover-image #item-header-avatar a { 1947 border: 0; 1948 text-decoration: none; 1949 } 1950 1951 #buddypress #item-header-cover-image #item-buttons { 1952 margin: 0 0 10px; 1953 padding: 0 0 5px; 1954 } 1955 1956 #buddypress #item-header-cover-image #item-buttons:after { 1957 clear: both; 1958 content: ""; 1959 display: table; 1960 } 1961 1962 @media screen and (max-width: 782px) { 1963 #buddypress #item-header-cover-image #item-header-avatar, 1964 .bp-user #buddypress #item-header #item-header-cover-image #item-header-avatar, 1965 #buddypress div#item-header #item-header-cover-image #item-header-content { 1966 width: 100%; 1967 text-align: center; 1968 } 1969 1970 #buddypress #item-header-cover-image #item-header-avatar a { 1971 display: inline-block; 1972 } 1973 1974 #buddypress #item-header-cover-image #item-header-avatar img { 1975 margin: 0; 1976 } 1977 1978 #buddypress div#item-header #item-header-cover-image #item-header-content, 1979 body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-header-content, 1980 body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions { 1981 margin: 0; 1982 } 1983 1984 body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-header-content, 1985 body.single-item.groups #buddypress div#item-header #item-header-cover-image #item-actions { 1986 max-width: 100%; 1987 } 1988 1989 #buddypress div#item-header-cover-image h2 a, 1990 #buddypress div#item-header-cover-image h2 { 1991 color: inherit; 1992 text-shadow: none; 1993 margin: 25px 0 0; 1994 font-size: 200%; 1995 } 1996 1997 #buddypress #item-header-cover-image #item-buttons div { 1998 float: none; 1999 display: inline-block; 2000 } 2001 2002 #buddypress #item-header-cover-image #item-buttons:before { 2003 content: ""; 2004 } 2005 2006 #buddypress #item-header-cover-image #item-buttons { 2007 margin: 5px 0; 2008 } 2009 } 2010 '; 2011 } 2012 2013 /** 2014 * Add a search box to a single group's manage members screen. 2015 * 2016 * @since 2.7.0 2017 * 2018 * @return string|null HTML for the search form. 2019 */ 2020 function bp_legacy_theme_group_manage_members_add_search() { 2021 if ( bp_is_action_variable( 'manage-members' ) ) : 2022 ?> 2023 <div id="members-dir-search" class="dir-search no-ajax" role="search"> 2024 <?php bp_directory_members_search_form(); ?> 2025 </div> 2026 <?php 2027 endif; 2028 } 2029 2030 /** 2031 * Modify welcome message in Legacy template pack when 2032 * community invitations are enabled. 2033 * 2034 * @since 8.0.0 2035 */ 2036 function bp_members_invitations_add_legacy_welcome_message() { 2037 $message = bp_members_invitations_get_registration_welcome_message(); 2038 2039 if ( $message ) { 2040 // Surround the message with `<p>` tags. 2041 echo wpautop( $message ); 2042 } 2043 } 2044 add_action( 'bp_before_register_page', 'bp_members_invitations_add_legacy_welcome_message' ); 2045 2046 2047 /** 2048 * Modify "registration disabled" message in Legacy template pack when 2049 * community invitations are enabled. 2050 * 2051 * @since 8.0.0 2052 */ 2053 function bp_members_invitations_add_legacy_registration_disabled_message() { 2054 $message = bp_members_invitations_get_modified_registration_disabled_message(); 2055 2056 if ( $message ) { 2057 // Surround the message with `<p>` tags. 2058 echo wpautop( $message ); 2059 } 2060 } 2061 add_action( 'bp_after_registration_disabled', 'bp_members_invitations_add_legacy_registration_disabled_message' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Dec 6 01:00:58 2024 | Cross-referenced by PHPXref 0.7.1 |