/bp-templates/bp-legacy/buddypress-functions.php

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