/bp-themes/bp-default/_inc/ajax.php

  1. <?php 
  2. /** 
  3. * AJAX Functions 
  4. * 
  5. * All of these functions enhance the responsiveness of the user interface in 
  6. * the default theme by adding AJAX functionality. 
  7. * 
  8. * For more information on how the custom AJAX functions work, see 
  9. * http://codex.wordpress.org/AJAX_in_Plugins. 
  10. * 
  11. * @package BuddyPress 
  12. * @since BuddyPress (1.2) 
  13. * @subpackage BP-Default 
  14. */ 
  15.  
  16. // Exit if accessed directly 
  17. if ( ! defined( 'ABSPATH' ) ) exit; 
  18.  
  19. /** 
  20. * Register AJAX handlers for BP Default theme functionality. 
  21. * 
  22. * This function is registered to the after_setup_theme hook with priority 20 as 
  23. * this file is included in a function hooked to after_setup_theme at priority 10. 
  24. * 
  25. * @since BuddyPress (1.6) 
  26. */ 
  27. function bp_dtheme_register_actions() { 
  28. $actions = array( 
  29. // Directory filters 
  30. 'blogs_filter' => 'bp_dtheme_object_template_loader',  
  31. 'forums_filter' => 'bp_dtheme_object_template_loader',  
  32. 'groups_filter' => 'bp_dtheme_object_template_loader',  
  33. 'members_filter' => 'bp_dtheme_object_template_loader',  
  34. 'messages_filter' => 'bp_dtheme_messages_template_loader',  
  35.  
  36. // Friends 
  37. 'accept_friendship' => 'bp_dtheme_ajax_accept_friendship',  
  38. 'addremove_friend' => 'bp_dtheme_ajax_addremove_friend',  
  39. 'reject_friendship' => 'bp_dtheme_ajax_reject_friendship',  
  40.  
  41. // Activity 
  42. 'activity_get_older_updates' => 'bp_dtheme_activity_template_loader',  
  43. 'activity_mark_fav' => 'bp_dtheme_mark_activity_favorite',  
  44. 'activity_mark_unfav' => 'bp_dtheme_unmark_activity_favorite',  
  45. 'activity_widget_filter' => 'bp_dtheme_activity_template_loader',  
  46. 'delete_activity' => 'bp_dtheme_delete_activity',  
  47. 'delete_activity_comment' => 'bp_dtheme_delete_activity_comment',  
  48. 'get_single_activity_content' => 'bp_dtheme_get_single_activity_content',  
  49. 'new_activity_comment' => 'bp_dtheme_new_activity_comment',  
  50. 'post_update' => 'bp_dtheme_post_update',  
  51. 'bp_spam_activity' => 'bp_dtheme_spam_activity',  
  52. 'bp_spam_activity_comment' => 'bp_dtheme_spam_activity',  
  53.  
  54. // Groups 
  55. 'groups_invite_user' => 'bp_dtheme_ajax_invite_user',  
  56. 'joinleave_group' => 'bp_dtheme_ajax_joinleave_group',  
  57.  
  58. // Messages 
  59. 'messages_autocomplete_results' => 'bp_dtheme_ajax_messages_autocomplete_results',  
  60. 'messages_close_notice' => 'bp_dtheme_ajax_close_notice',  
  61. 'messages_delete' => 'bp_dtheme_ajax_messages_delete',  
  62. 'messages_markread' => 'bp_dtheme_ajax_message_markread',  
  63. 'messages_markunread' => 'bp_dtheme_ajax_message_markunread',  
  64. 'messages_send_reply' => 'bp_dtheme_ajax_messages_send_reply',  
  65. ); 
  66.  
  67. /** 
  68. * Register all of these AJAX handlers 
  69. * 
  70. * The "wp_ajax_" action is used for logged in users, and "wp_ajax_nopriv_" 
  71. * executes for users that aren't logged in. This is for backpat with BP <1.6. 
  72. */ 
  73. foreach( $actions as $name => $function ) { 
  74. add_action( 'wp_ajax_' . $name, $function ); 
  75. add_action( 'wp_ajax_nopriv_' . $name, $function ); 
  76. add_action( 'after_setup_theme', 'bp_dtheme_register_actions', 20 ); 
  77.  
  78. /** 
  79. * This function looks scarier than it actually is. :) 
  80. * Each object loop (activity/members/groups/blogs/forums) contains default parameters to 
  81. * show specific information based on the page we are currently looking at. 
  82. * The following function will take into account any cookies set in the JS and allow us 
  83. * to override the parameters sent. That way we can change the results returned without reloading the page. 
  84. * By using cookies we can also make sure that user settings are retained across page loads. 
  85. * 
  86. * @return string Query string for the activity/members/groups/blogs/forums loops 
  87. * @since BuddyPress (1.2) 
  88. */ 
  89. function bp_dtheme_ajax_querystring( $query_string, $object ) { 
  90. if ( empty( $object ) ) 
  91. return ''; 
  92.  
  93. // Set up the cookies passed on this AJAX request. Store a local var to avoid conflicts 
  94. if ( ! empty( $_POST['cookie'] ) ) 
  95. $_BP_COOKIE = wp_parse_args( str_replace( '; ', '&', urldecode( $_POST['cookie'] ) ) ); 
  96. else 
  97. $_BP_COOKIE = &$_COOKIE; 
  98.  
  99. $qs = array(); 
  100.  
  101. /** 
  102. * Check if any cookie values are set. If there are then override the default params passed to the 
  103. * template loop 
  104. */ 
  105.  
  106. // Activity stream filtering on action 
  107. if ( ! empty( $_BP_COOKIE['bp-' . $object . '-filter'] ) && '-1' != $_BP_COOKIE['bp-' . $object . '-filter'] ) { 
  108. $qs[] = 'type=' . $_BP_COOKIE['bp-' . $object . '-filter']; 
  109. $qs[] = 'action=' . $_BP_COOKIE['bp-' . $object . '-filter']; 
  110.  
  111. if ( ! empty( $_BP_COOKIE['bp-' . $object . '-scope'] ) ) { 
  112. if ( 'personal' == $_BP_COOKIE['bp-' . $object . '-scope'] ) { 
  113. $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id(); 
  114. $qs[] = 'user_id=' . $user_id; 
  115.  
  116. // Activity stream scope only on activity directory. 
  117. if ( 'all' != $_BP_COOKIE['bp-' . $object . '-scope'] && ! bp_displayed_user_id() && ! bp_is_single_item() ) 
  118. $qs[] = 'scope=' . $_BP_COOKIE['bp-' . $object . '-scope']; 
  119.  
  120. // If page and search_terms have been passed via the AJAX post request, use those. 
  121. if ( ! empty( $_POST['page'] ) && '-1' != $_POST['page'] ) 
  122. $qs[] = 'page=' . absint( $_POST['page'] ); 
  123.  
  124. // exludes activity just posted and avoids duplicate ids 
  125. if ( ! empty( $_POST['exclude_just_posted'] ) ) { 
  126. $just_posted = wp_parse_id_list( $_POST['exclude_just_posted'] ); 
  127. $qs[] = 'exclude=' . implode( ', ', $just_posted ); 
  128.  
  129. $object_search_text = bp_get_search_default_text( $object ); 
  130. if ( ! empty( $_POST['search_terms'] ) && $object_search_text != $_POST['search_terms'] && 'false' != $_POST['search_terms'] && 'undefined' != $_POST['search_terms'] ) 
  131. $qs[] = 'search_terms=' . $_POST['search_terms']; 
  132.  
  133. // Now pass the querystring to override default values. 
  134. $query_string = empty( $qs ) ? '' : join( '&', (array) $qs ); 
  135.  
  136. $object_filter = ''; 
  137. if ( isset( $_BP_COOKIE['bp-' . $object . '-filter'] ) ) 
  138. $object_filter = $_BP_COOKIE['bp-' . $object . '-filter']; 
  139.  
  140. $object_scope = ''; 
  141. if ( isset( $_BP_COOKIE['bp-' . $object . '-scope'] ) ) 
  142. $object_scope = $_BP_COOKIE['bp-' . $object . '-scope']; 
  143.  
  144. $object_page = ''; 
  145. if ( isset( $_BP_COOKIE['bp-' . $object . '-page'] ) ) 
  146. $object_page = $_BP_COOKIE['bp-' . $object . '-page']; 
  147.  
  148. $object_search_terms = ''; 
  149. if ( isset( $_BP_COOKIE['bp-' . $object . '-search-terms'] ) ) 
  150. $object_search_terms = $_BP_COOKIE['bp-' . $object . '-search-terms']; 
  151.  
  152. $object_extras = ''; 
  153. if ( isset( $_BP_COOKIE['bp-' . $object . '-extras'] ) ) 
  154. $object_extras = $_BP_COOKIE['bp-' . $object . '-extras']; 
  155.  
  156. return apply_filters( 'bp_dtheme_ajax_querystring', $query_string, $object, $object_filter, $object_scope, $object_page, $object_search_terms, $object_extras ); 
  157. add_filter( 'bp_ajax_querystring', 'bp_dtheme_ajax_querystring', 10, 2 ); 
  158.  
  159. /** 
  160. * Load the template loop for the current object. 
  161. * 
  162. * @return string Prints template loop for the specified object 
  163. * @since BuddyPress (1.2) 
  164. */ 
  165. function bp_dtheme_object_template_loader() { 
  166. // Bail if not a POST action 
  167. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  168. return; 
  169.  
  170. // Bail if no object passed 
  171. if ( empty( $_POST['object'] ) ) 
  172. return; 
  173.  
  174. // Sanitize the object 
  175. $object = sanitize_title( $_POST['object'] ); 
  176.  
  177. // Bail if object is not an active component 
  178. if ( ! bp_is_active( $object ) ) 
  179. return; 
  180.  
  181. /** 
  182. * AJAX requests happen too early to be seen by bp_update_is_directory() 
  183. * so we do it manually here to ensure templates load with the correct 
  184. * context. Without this check, templates will load the 'single' version 
  185. * of themselves rather than the directory version. 
  186. */ 
  187. if ( ! bp_current_action() ) 
  188. bp_update_is_directory( true, bp_current_component() ); 
  189.  
  190. // Locate the object template 
  191. locate_template( array( "$object/$object-loop.php" ), true ); 
  192. exit; 
  193.  
  194. /** 
  195. * Load messages template loop when searched on the private message page 
  196. * 
  197. * @return string Prints template loop for the Messages component 
  198. * @since BuddyPress (1.6) 
  199. */ 
  200. function bp_dtheme_messages_template_loader() { 
  201. locate_template( array( 'members/single/messages/messages-loop.php' ), true ); 
  202. exit; 
  203.  
  204. /** 
  205. * Load the activity loop template when activity is requested via AJAX,  
  206. * 
  207. * @return string JSON object containing 'contents' (output of the template loop for the Activity component) and 'feed_url' (URL to the relevant RSS feed). 
  208. * @since BuddyPress (1.2) 
  209. */ 
  210. function bp_dtheme_activity_template_loader() { 
  211. // Bail if not a POST action 
  212. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  213. return; 
  214.  
  215. $scope = ''; 
  216. if ( ! empty( $_POST['scope'] ) ) 
  217. $scope = $_POST['scope']; 
  218.  
  219. // We need to calculate and return the feed URL for each scope 
  220. switch ( $scope ) { 
  221. case 'friends': 
  222. $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/friends/feed/'; 
  223. break; 
  224. case 'groups': 
  225. $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/groups/feed/'; 
  226. break; 
  227. case 'favorites': 
  228. $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/favorites/feed/'; 
  229. break; 
  230. case 'mentions': 
  231. $feed_url = bp_loggedin_user_domain() . bp_get_activity_slug() . '/mentions/feed/'; 
  232. bp_activity_clear_new_mentions( bp_loggedin_user_id() ); 
  233. break; 
  234. default: 
  235. $feed_url = home_url( bp_get_activity_root_slug() . '/feed/' ); 
  236. break; 
  237.  
  238. // Buffer the loop in the template to a var for JS to spit out. 
  239. ob_start(); 
  240. locate_template( array( 'activity/activity-loop.php' ), true ); 
  241. $result['contents'] = ob_get_contents(); 
  242. $result['feed_url'] = apply_filters( 'bp_dtheme_activity_feed_url', $feed_url, $scope ); 
  243. ob_end_clean(); 
  244.  
  245. exit( json_encode( $result ) ); 
  246.  
  247. /** 
  248. * Processes Activity updates received via a POST request. 
  249. * 
  250. * @return string HTML 
  251. * @since BuddyPress (1.2) 
  252. */ 
  253. function bp_dtheme_post_update() { 
  254. // Bail if not a POST action 
  255. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  256. return; 
  257.  
  258. // Check the nonce 
  259. check_admin_referer( 'post_update', '_wpnonce_post_update' ); 
  260.  
  261. if ( ! is_user_logged_in() ) 
  262. exit( '-1' ); 
  263.  
  264. if ( empty( $_POST['content'] ) ) 
  265. exit( '-1<div id="message" class="error"><p>' . __( 'Please enter some content to post.', 'buddypress' ) . '</p></div>' ); 
  266.  
  267. $activity_id = 0; 
  268. if ( empty( $_POST['object'] ) && bp_is_active( 'activity' ) ) { 
  269. $activity_id = bp_activity_post_update( array( 'content' => $_POST['content'], 'error_type' => 'wp_error' ) ); 
  270.  
  271. } elseif ( $_POST['object'] == 'groups' ) { 
  272. if ( ! empty( $_POST['item_id'] ) && bp_is_active( 'groups' ) ) 
  273. $activity_id = groups_post_update( array( 'content' => $_POST['content'], 'group_id' => $item_id, 'error_type' => 'wp_error' ) ); 
  274.  
  275. } else { 
  276. $activity_id = apply_filters( 'bp_activity_custom_update', $_POST['object'], $_POST['item_id'], $_POST['content'] ); 
  277.  
  278. if ( false === $activity_id ) { 
  279. exit( '-1<div id="message" class="error"><p>' . __( 'There was a problem posting your update, please try again.', 'buddypress' ) . '</p></div>' ); 
  280. } elseif ( is_wp_error( $activity_id ) && $activity_id->get_error_code() ) { 
  281. exit( '-1<div id="message" class="error bp-ajax-message"><p>' . $activity_id->get_error_message() . '</p></div>' ); 
  282.  
  283. if ( bp_has_activities ( 'include=' . $activity_id ) ) { 
  284. while ( bp_activities() ) { 
  285. bp_the_activity(); 
  286. locate_template( array( 'activity/entry.php' ), true ); 
  287.  
  288. exit; 
  289.  
  290. /** 
  291. * Posts new Activity comments received via a POST request. 
  292. * 
  293. * @global BP_Activity_Template $activities_template 
  294. * @return string HTML 
  295. * @since BuddyPress (1.2) 
  296. */ 
  297. function bp_dtheme_new_activity_comment() { 
  298. global $activities_template; 
  299.  
  300. // Bail if not a POST action 
  301. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  302. return; 
  303.  
  304. // Check the nonce 
  305. check_admin_referer( 'new_activity_comment', '_wpnonce_new_activity_comment' ); 
  306.  
  307. if ( ! is_user_logged_in() ) 
  308. exit( '-1' ); 
  309.  
  310. if ( empty( $_POST['content'] ) ) 
  311. exit( '-1<div id="message" class="error"><p>' . __( 'Please do not leave the comment area blank.', 'buddypress' ) . '</p></div>' ); 
  312.  
  313. if ( empty( $_POST['form_id'] ) || empty( $_POST['comment_id'] ) || ! is_numeric( $_POST['form_id'] ) || ! is_numeric( $_POST['comment_id'] ) ) 
  314. exit( '-1<div id="message" class="error"><p>' . __( 'There was an error posting that reply, please try again.', 'buddypress' ) . '</p></div>' ); 
  315.  
  316. $comment_id = bp_activity_new_comment( array( 
  317. 'activity_id' => $_POST['form_id'],  
  318. 'content' => $_POST['content'],  
  319. 'parent_id' => $_POST['comment_id'],  
  320. 'error_type' => 'wp_error' 
  321. ) ); 
  322.  
  323. if ( false === $comment_id ) { 
  324. exit( '-1<div id="message" class="error"><p>' . __( 'There was an error posting that reply, please try again.', 'buddypress' ) . '</p></div>' ); 
  325. } elseif ( is_wp_error( $comment_id ) ) { 
  326. exit( '-1<div id="message" class="error bp-ajax-message"><p>' . esc_html( $comment_id->get_error_message() ) . '</p></div>' ); 
  327.  
  328. // Load the new activity item into the $activities_template global 
  329. bp_has_activities( 'display_comments=stream&hide_spam=false&show_hidden=true&include=' . $comment_id ); 
  330.  
  331. // Swap the current comment with the activity item we just loaded 
  332. $activities_template->activity = new stdClass; 
  333. $activities_template->activity->id = $activities_template->activities[0]->item_id; 
  334. $activities_template->activity->current_comment = $activities_template->activities[0]; 
  335.  
  336. $template = locate_template( 'activity/comment.php', false, false ); 
  337.  
  338. /** 
  339. * Backward compatibility. In older versions of BP, the markup was 
  340. * generated in the PHP instead of a template. This ensures that 
  341. * older themes (which are not children of bp-default and won't 
  342. * have the new template) will still work. 
  343. */ 
  344. if ( empty( $template ) ) 
  345. $template = buddypress()->plugin_dir . '/bp-themes/bp-default/activity/comment.php'; 
  346.  
  347. load_template( $template, false ); 
  348.  
  349. unset( $activities_template ); 
  350. exit; 
  351.  
  352. /** 
  353. * Deletes an Activity item received via a POST request. 
  354. * 
  355. * @return mixed String on error, void on success 
  356. * @since BuddyPress (1.2) 
  357. */ 
  358. function bp_dtheme_delete_activity() { 
  359. // Bail if not a POST action 
  360. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  361. return; 
  362.  
  363. // Check the nonce 
  364. check_admin_referer( 'bp_activity_delete_link' ); 
  365.  
  366. if ( ! is_user_logged_in() ) 
  367. exit( '-1' ); 
  368.  
  369. if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 
  370. exit( '-1' ); 
  371.  
  372. $activity = new BP_Activity_Activity( (int) $_POST['id'] ); 
  373.  
  374. // Check access 
  375. if ( ! bp_activity_user_can_delete( $activity ) ) 
  376. exit( '-1' ); 
  377.  
  378. // Call the action before the delete so plugins can still fetch information about it 
  379. do_action( 'bp_activity_before_action_delete_activity', $activity->id, $activity->user_id ); 
  380.  
  381. if ( ! bp_activity_delete( array( 'id' => $activity->id, 'user_id' => $activity->user_id ) ) ) 
  382. exit( '-1<div id="message" class="error"><p>' . __( 'There was a problem when deleting. Please try again.', 'buddypress' ) . '</p></div>' ); 
  383.  
  384. do_action( 'bp_activity_action_delete_activity', $activity->id, $activity->user_id ); 
  385. exit; 
  386.  
  387. /** 
  388. * Deletes an Activity comment received via a POST request 
  389. * 
  390. * @return mixed String on error, void on success 
  391. * @since BuddyPress (1.2) 
  392. */ 
  393. function bp_dtheme_delete_activity_comment() { 
  394. // Bail if not a POST action 
  395. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  396. return; 
  397.  
  398. // Check the nonce 
  399. check_admin_referer( 'bp_activity_delete_link' ); 
  400.  
  401. if ( ! is_user_logged_in() ) 
  402. exit( '-1' ); 
  403.  
  404. $comment = new BP_Activity_Activity( $_POST['id'] ); 
  405.  
  406. // Check access 
  407. if ( ! bp_current_user_can( 'bp_moderate' ) && $comment->user_id != bp_loggedin_user_id() ) 
  408. exit( '-1' ); 
  409.  
  410. if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 
  411. exit( '-1' ); 
  412.  
  413. // Call the action before the delete so plugins can still fetch information about it 
  414. do_action( 'bp_activity_before_action_delete_activity', $_POST['id'], $comment->user_id ); 
  415.  
  416. if ( ! bp_activity_delete_comment( $comment->item_id, $comment->id ) ) 
  417. exit( '-1<div id="message" class="error"><p>' . __( 'There was a problem when deleting. Please try again.', 'buddypress' ) . '</p></div>' ); 
  418.  
  419. do_action( 'bp_activity_action_delete_activity', $_POST['id'], $comment->user_id ); 
  420. exit; 
  421.  
  422. /** 
  423. * AJAX spam an activity item or comment 
  424. * 
  425. * @global BuddyPress $bp The one true BuddyPress instance 
  426. * @return mixed String on error, void on success 
  427. * @since BuddyPress (1.6) 
  428. */ 
  429. function bp_dtheme_spam_activity() { 
  430. global $bp; 
  431.  
  432. // Bail if not a POST action 
  433. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  434. return; 
  435.  
  436. // Check that user is logged in, Activity Streams are enabled, and Akismet is present. 
  437. if ( ! is_user_logged_in() || ! bp_is_active( 'activity' ) || empty( $bp->activity->akismet ) ) 
  438. exit( '-1' ); 
  439.  
  440. // Check an item ID was passed 
  441. if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 
  442. exit( '-1' ); 
  443.  
  444. // Is the current user allowed to spam items? 
  445. if ( ! bp_activity_user_can_mark_spam() ) 
  446. exit( '-1' ); 
  447.  
  448. // Load up the activity item 
  449. $activity = new BP_Activity_Activity( (int) $_POST['id'] ); 
  450. if ( empty( $activity->component ) ) 
  451. exit( '-1' ); 
  452.  
  453. // Check nonce 
  454. check_admin_referer( 'bp_activity_akismet_spam_' . $activity->id ); 
  455.  
  456. // Call an action before the spamming so plugins can modify things if they want to 
  457. do_action( 'bp_activity_before_action_spam_activity', $activity->id, $activity ); 
  458.  
  459. // Mark as spam 
  460. bp_activity_mark_as_spam( $activity ); 
  461. $activity->save(); 
  462.  
  463. do_action( 'bp_activity_action_spam_activity', $activity->id, $activity->user_id ); 
  464. exit; 
  465.  
  466. /** 
  467. * Mark an activity as a favourite via a POST request. 
  468. * 
  469. * @return string HTML 
  470. * @since BuddyPress (1.2) 
  471. */ 
  472. function bp_dtheme_mark_activity_favorite() { 
  473. // Bail if not a POST action 
  474. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  475. return; 
  476.  
  477. if ( bp_activity_add_user_favorite( $_POST['id'] ) ) 
  478. _e( 'Remove Favorite', 'buddypress' ); 
  479. else 
  480. _e( 'Favorite', 'buddypress' ); 
  481.  
  482. exit; 
  483.  
  484. /** 
  485. * Un-favourite an activity via a POST request. 
  486. * 
  487. * @return string HTML 
  488. * @since BuddyPress (1.2) 
  489. */ 
  490. function bp_dtheme_unmark_activity_favorite() { 
  491. // Bail if not a POST action 
  492. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  493. return; 
  494.  
  495. if ( bp_activity_remove_user_favorite( $_POST['id'] ) ) 
  496. _e( 'Favorite', 'buddypress' ); 
  497. else 
  498. _e( 'Remove Favorite', 'buddypress' ); 
  499.  
  500. exit; 
  501.  
  502. /** 
  503. * Fetches full an activity's full, non-excerpted content via a POST request. 
  504. * Used for the 'Read More' link on long activity items. 
  505. * 
  506. * @return string HTML 
  507. * @since BuddyPress (1.5) 
  508. */ 
  509. function bp_dtheme_get_single_activity_content() { 
  510. // Bail if not a POST action 
  511. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  512. return; 
  513.  
  514. $activity_array = bp_activity_get_specific( array( 
  515. 'activity_ids' => $_POST['activity_id'],  
  516. 'display_comments' => 'stream' 
  517. ) ); 
  518.  
  519. $activity = ! empty( $activity_array['activities'][0] ) ? $activity_array['activities'][0] : false; 
  520.  
  521. if ( empty( $activity ) ) 
  522. exit; // @todo: error? 
  523.  
  524. do_action_ref_array( 'bp_dtheme_get_single_activity_content', array( &$activity ) ); 
  525.  
  526. // Activity content retrieved through AJAX should run through normal filters, but not be truncated 
  527. remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 ); 
  528. $content = apply_filters( 'bp_get_activity_content_body', $activity->content ); 
  529.  
  530. exit( $content ); 
  531.  
  532. /** 
  533. * Invites a friend to join a group via a POST request. 
  534. * 
  535. * @since BuddyPress (1.2) 
  536. * @todo Audit return types 
  537. */ 
  538. function bp_dtheme_ajax_invite_user() { 
  539. // Bail if not a POST action 
  540. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  541. return; 
  542.  
  543. check_ajax_referer( 'groups_invite_uninvite_user' ); 
  544.  
  545. if ( ! $_POST['friend_id'] || ! $_POST['friend_action'] || ! $_POST['group_id'] ) 
  546. return; 
  547.  
  548. if ( ! bp_groups_user_can_send_invites( $_POST['group_id'] ) ) 
  549. return; 
  550.  
  551. if ( ! friends_check_friendship( bp_loggedin_user_id(), $_POST['friend_id'] ) ) 
  552. return; 
  553.  
  554. $group_id = (int) $_POST['group_id']; 
  555. $friend_id = (int) $_POST['friend_id']; 
  556.  
  557. if ( 'invite' == $_POST['friend_action'] ) { 
  558. $group = groups_get_group( $group_id ); 
  559.  
  560. // Users who have previously requested membership do not need 
  561. // another invitation created for them 
  562. if ( BP_Groups_Member::check_for_membership_request( $friend_id, $group_id ) ) { 
  563. $user_status = 'is_pending'; 
  564.  
  565. // Create the user invitation 
  566. } else if ( groups_invite_user( array( 'user_id' => $friend_id, 'group_id' => $group_id ) ) ) { 
  567. $user_status = 'is_invited'; 
  568.  
  569. // Miscellaneous failure 
  570. } else { 
  571. return; 
  572.  
  573. $user = new BP_Core_User( $_POST['friend_id'] ); 
  574.  
  575. echo '<li id="uid-' . $user->id . '">'; 
  576. echo $user->avatar_thumb; 
  577. echo '<h4>' . $user->user_link . '</h4>'; 
  578. echo '<span class="activity">' . esc_attr( $user->last_active ) . '</span>'; 
  579. echo '<div class="action"> 
  580. <a class="button remove" href="' . wp_nonce_url( bp_loggedin_user_domain() . bp_get_groups_slug() . '/' . $_POST['group_id'] . '/invites/remove/' . $user->id, 'groups_invite_uninvite_user' ) . '" id="uid-' . esc_attr( $user->id ) . '">' . __( 'Remove Invite', 'buddypress' ) . '</a> 
  581. </div>'; 
  582.  
  583. if ( 'is_pending' == $user_status ) { 
  584. 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>'; 
  585.  
  586. echo '</li>'; 
  587. exit; 
  588.  
  589. } elseif ( 'uninvite' == $_POST['friend_action'] ) { 
  590. // Users who have previously requested membership should not 
  591. // have their requests deleted on the "uninvite" action 
  592. if ( BP_Groups_Member::check_for_membership_request( $friend_id, $group_id ) ) { 
  593. return; 
  594.  
  595. // Remove the unsent invitation 
  596. if ( ! groups_uninvite_user( $friend_id, $group_id ) ) { 
  597. return; 
  598.  
  599. exit; 
  600.  
  601. } else { 
  602. return; 
  603.  
  604. /** 
  605. * Friend/un-friend a user via a POST request. 
  606. * 
  607. * @return string HTML 
  608. * @since BuddyPress (1.2) 
  609. */ 
  610. function bp_dtheme_ajax_addremove_friend() { 
  611. // Bail if not a POST action 
  612. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  613. return; 
  614.  
  615. // Cast fid as an integer 
  616. $friend_id = (int) $_POST['fid']; 
  617.  
  618. // Trying to cancel friendship 
  619. if ( 'is_friend' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  620. check_ajax_referer( 'friends_remove_friend' ); 
  621.  
  622. if ( ! friends_remove_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  623. echo __( 'Friendship could not be canceled.', 'buddypress' ); 
  624. } else { 
  625. echo '<a id="friend-' . esc_attr( $friend_id ) . '" class="add" rel="add" title="' . __( 'Add Friend', 'buddypress' ) . '" href="' . wp_nonce_url( bp_loggedin_user_domain() . bp_get_friends_slug() . '/add-friend/' . $friend_id, 'friends_add_friend' ) . '">' . __( 'Add Friend', 'buddypress' ) . '</a>'; 
  626.  
  627. // Trying to request friendship 
  628. } elseif ( 'not_friends' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  629. check_ajax_referer( 'friends_add_friend' ); 
  630.  
  631. if ( ! friends_add_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  632. echo __(' Friendship could not be requested.', 'buddypress' ); 
  633. } else { 
  634. echo '<a id="friend-' . esc_attr( $friend_id ) . '" class="remove" rel="remove" title="' . __( 'Cancel Friendship Request', 'buddypress' ) . '" 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>'; 
  635.  
  636. // Trying to cancel pending request 
  637. } elseif ( 'pending' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  638. check_ajax_referer( 'friends_withdraw_friendship' ); 
  639.  
  640. if ( friends_withdraw_friendship( bp_loggedin_user_id(), $friend_id ) ) { 
  641. echo '<a id="friend-' . esc_attr( $friend_id ) . '" class="add" rel="add" title="' . __( 'Add Friend', 'buddypress' ) . '" href="' . wp_nonce_url( bp_loggedin_user_domain() . bp_get_friends_slug() . '/add-friend/' . $friend_id, 'friends_add_friend' ) . '">' . __( 'Add Friend', 'buddypress' ) . '</a>'; 
  642. } else { 
  643. echo __("Friendship request could not be cancelled.", 'buddypress'); 
  644.  
  645. // Request already pending 
  646. } else { 
  647. echo __( 'Request Pending', 'buddypress' ); 
  648.  
  649. exit; 
  650.  
  651. /** 
  652. * Accept a user friendship request via a POST request. 
  653. * 
  654. * @return mixed String on error, void on success 
  655. * @since BuddyPress (1.2) 
  656. */ 
  657. function bp_dtheme_ajax_accept_friendship() { 
  658. // Bail if not a POST action 
  659. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  660. return; 
  661.  
  662. check_admin_referer( 'friends_accept_friendship' ); 
  663.  
  664. if ( ! friends_accept_friendship( (int) $_POST['id'] ) ) 
  665. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem accepting that request. Please try again.', 'buddypress' ) . '</p></div>'; 
  666.  
  667. exit; 
  668.  
  669. /** 
  670. * Reject a user friendship request via a POST request. 
  671. * 
  672. * @return mixed String on error, void on success 
  673. * @since BuddyPress (1.2) 
  674. */ 
  675. function bp_dtheme_ajax_reject_friendship() { 
  676. // Bail if not a POST action 
  677. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  678. return; 
  679.  
  680. check_admin_referer( 'friends_reject_friendship' ); 
  681.  
  682. if ( ! friends_reject_friendship( (int) $_POST['id'] ) ) 
  683. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem rejecting that request. Please try again.', 'buddypress' ) . '</p></div>'; 
  684.  
  685. exit; 
  686.  
  687. /** 
  688. * Join or leave a group when clicking the "join/leave" button via a POST request. 
  689. * 
  690. * @return string HTML 
  691. * @since BuddyPress (1.2) 
  692. */ 
  693. function bp_dtheme_ajax_joinleave_group() { 
  694. // Bail if not a POST action 
  695. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  696. return; 
  697.  
  698. // Cast gid as integer 
  699. $group_id = (int) $_POST['gid']; 
  700.  
  701. if ( groups_is_user_banned( bp_loggedin_user_id(), $group_id ) ) 
  702. return; 
  703.  
  704. if ( ! $group = groups_get_group( array( 'group_id' => $group_id ) ) ) 
  705. return; 
  706.  
  707. if ( ! groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) { 
  708. if ( 'public' == $group->status ) { 
  709. check_ajax_referer( 'groups_join_group' ); 
  710.  
  711. if ( ! groups_join_group( $group->id ) ) { 
  712. _e( 'Error joining group', 'buddypress' ); 
  713. } else { 
  714. echo '<a id="group-' . esc_attr( $group->id ) . '" class="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>'; 
  715.  
  716. } elseif ( 'private' == $group->status ) { 
  717.  
  718. // If the user has already been invited, then this is 
  719. // an Accept Invitation button 
  720. if ( groups_check_user_has_invite( bp_loggedin_user_id(), $group->id ) ) { 
  721. check_ajax_referer( 'groups_accept_invite' ); 
  722.  
  723. if ( ! groups_accept_invite( bp_loggedin_user_id(), $group->id ) ) { 
  724. _e( 'Error requesting membership', 'buddypress' ); 
  725. } else { 
  726. echo '<a id="group-' . esc_attr( $group->id ) . '" class="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>'; 
  727.  
  728. // Otherwise, it's a Request Membership button 
  729. } else { 
  730. check_ajax_referer( 'groups_request_membership' ); 
  731.  
  732. if ( ! groups_send_membership_request( bp_loggedin_user_id(), $group->id ) ) { 
  733. _e( 'Error requesting membership', 'buddypress' ); 
  734. } else { 
  735. echo '<a id="group-' . esc_attr( $group->id ) . '" class="membership-requested" rel="membership-requested" title="' . __( 'Membership Requested', 'buddypress' ) . '" href="' . bp_get_group_permalink( $group ) . '">' . __( 'Membership Requested', 'buddypress' ) . '</a>'; 
  736.  
  737. } else { 
  738. check_ajax_referer( 'groups_leave_group' ); 
  739.  
  740. if ( ! groups_leave_group( $group->id ) ) { 
  741. _e( 'Error leaving group', 'buddypress' ); 
  742. } elseif ( 'public' == $group->status ) { 
  743. echo '<a id="group-' . esc_attr( $group->id ) . '" class="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>'; 
  744. } elseif ( 'private' == $group->status ) { 
  745. echo '<a id="group-' . esc_attr( $group->id ) . '" class="request-membership" rel="join" title="' . __( 'Request Membership', 'buddypress' ) . '" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'request-membership', 'groups_send_membership_request' ) . '">' . __( 'Request Membership', 'buddypress' ) . '</a>'; 
  746.  
  747. exit; 
  748.  
  749. /** 
  750. * Close and keep closed site wide notices from an admin in the sidebar, via a POST request. 
  751. * 
  752. * @return mixed String on error, void on success 
  753. * @since BuddyPress (1.2) 
  754. */ 
  755. function bp_dtheme_ajax_close_notice() { 
  756. // Bail if not a POST action 
  757. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  758. return; 
  759.  
  760. if ( ! isset( $_POST['notice_id'] ) ) { 
  761. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem closing the notice.', 'buddypress' ) . '</p></div>'; 
  762.  
  763. } else { 
  764. $user_id = get_current_user_id(); 
  765. $notice_ids = bp_get_user_meta( $user_id, 'closed_notices', true ); 
  766. $notice_ids[] = (int) $_POST['notice_id']; 
  767.  
  768. bp_update_user_meta( $user_id, 'closed_notices', $notice_ids ); 
  769.  
  770. exit; 
  771.  
  772. /** 
  773. * Send a private message reply to a thread via a POST request. 
  774. * 
  775. * @return string HTML 
  776. * @since BuddyPress (1.2) 
  777. */ 
  778. function bp_dtheme_ajax_messages_send_reply() { 
  779. // Bail if not a POST action 
  780. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  781. return; 
  782.  
  783. check_ajax_referer( 'messages_send_message' ); 
  784.  
  785. $result = messages_new_message( array( 'thread_id' => (int) $_REQUEST['thread_id'], 'content' => $_REQUEST['content'] ) ); 
  786.  
  787. if ( $result ) { ?> 
  788. <div class="message-box new-message"> 
  789. <div class="message-metadata"> 
  790. <?php do_action( 'bp_before_message_meta' ); ?> 
  791. <?php echo bp_loggedin_user_avatar( 'type=thumb&width=30&height=30' ); ?> 
  792.  
  793. <strong><a href="<?php echo bp_loggedin_user_domain(); ?>"><?php bp_loggedin_user_fullname(); ?></a> <span class="activity"><?php printf( __( 'Sent %s', 'buddypress' ), bp_core_time_since( bp_core_current_time() ) ); ?></span></strong> 
  794.  
  795. <?php do_action( 'bp_after_message_meta' ); ?> 
  796. </div> 
  797.  
  798. <?php do_action( 'bp_before_message_content' ); ?> 
  799.  
  800. <div class="message-content"> 
  801. <?php echo stripslashes( apply_filters( 'bp_get_the_thread_message_content', $_REQUEST['content'] ) ); ?> 
  802. </div> 
  803.  
  804. <?php do_action( 'bp_after_message_content' ); ?> 
  805.  
  806. <div class="clear"></div> 
  807. </div> 
  808. <?php 
  809. } else { 
  810. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem sending that reply. Please try again.', 'buddypress' ) . '</p></div>'; 
  811.  
  812. exit; 
  813.  
  814. /** 
  815. * Mark a private message as unread in your inbox via a POST request. 
  816. * 
  817. * @return mixed String on error, void on success 
  818. * @since BuddyPress (1.2) 
  819. */ 
  820. function bp_dtheme_ajax_message_markunread() { 
  821. // Bail if not a POST action 
  822. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  823. return; 
  824.  
  825. if ( ! isset($_POST['thread_ids']) ) { 
  826. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem marking messages as unread.', 'buddypress' ) . '</p></div>'; 
  827.  
  828. } else { 
  829. $thread_ids = explode( ', ', $_POST['thread_ids'] ); 
  830.  
  831. for ( $i = 0, $count = count( $thread_ids ); $i < $count; ++$i ) { 
  832. BP_Messages_Thread::mark_as_unread( (int) $thread_ids[$i] ); 
  833.  
  834. exit; 
  835.  
  836. /** 
  837. * Mark a private message as read in your inbox via a POST request. 
  838. * 
  839. * @return mixed String on error, void on success 
  840. * @since BuddyPress (1.2) 
  841. */ 
  842. function bp_dtheme_ajax_message_markread() { 
  843. // Bail if not a POST action 
  844. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  845. return; 
  846.  
  847. if ( ! isset($_POST['thread_ids']) ) { 
  848. echo "-1<div id='message' class='error'><p>" . __('There was a problem marking messages as read.', 'buddypress' ) . '</p></div>'; 
  849.  
  850. } else { 
  851. $thread_ids = explode( ', ', $_POST['thread_ids'] ); 
  852.  
  853. for ( $i = 0, $count = count( $thread_ids ); $i < $count; ++$i ) { 
  854. BP_Messages_Thread::mark_as_read( (int) $thread_ids[$i] ); 
  855.  
  856. exit; 
  857.  
  858. /** 
  859. * Delete a private message(s) in your inbox via a POST request. 
  860. * 
  861. * @return string HTML 
  862. * @since BuddyPress (1.2) 
  863. */ 
  864. function bp_dtheme_ajax_messages_delete() { 
  865. // Bail if not a POST action 
  866. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  867. return; 
  868.  
  869. if ( ! isset($_POST['thread_ids']) ) { 
  870. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem deleting messages.', 'buddypress' ) . '</p></div>'; 
  871.  
  872. } else { 
  873. $thread_ids = explode( ', ', $_POST['thread_ids'] ); 
  874.  
  875. for ( $i = 0, $count = count( $thread_ids ); $i < $count; ++$i ) { 
  876. BP_Messages_Thread::delete( (int) $thread_ids[$i] ); 
  877.  
  878. _e( 'Messages deleted.', 'buddypress' ); 
  879.  
  880. exit; 
  881.  
  882. /** 
  883. * AJAX handler for autocomplete. Displays friends only, unless BP_MESSAGES_AUTOCOMPLETE_ALL is defined. 
  884. * 
  885. * @return string HTML 
  886. * @since BuddyPress (1.2) 
  887. */ 
  888. function bp_dtheme_ajax_messages_autocomplete_results() { 
  889.  
  890. // Include everyone in the autocomplete, or just friends? 
  891. if ( bp_is_current_component( bp_get_messages_slug() ) ) 
  892. $autocomplete_all = buddypress()->messages->autocomplete_all; 
  893.  
  894. $pag_page = 1; 
  895. $limit = (int) $_GET['limit'] ? $_GET['limit'] : apply_filters( 'bp_autocomplete_max_results', 10 ); 
  896.  
  897. // Get the user ids based on the search terms 
  898. if ( ! empty( $autocomplete_all ) ) { 
  899. $users = BP_Core_User::search_users( $_GET['q'], $limit, $pag_page ); 
  900.  
  901. if ( ! empty( $users['users'] ) ) { 
  902. // Build an array with the correct format 
  903. $user_ids = array(); 
  904. foreach( $users['users'] as $user ) { 
  905. if ( $user->id != bp_loggedin_user_id() ) { 
  906. $user_ids[] = $user->id; 
  907.  
  908. $user_ids = apply_filters( 'bp_core_autocomplete_ids', $user_ids, $_GET['q'], $limit ); 
  909.  
  910. } else { 
  911. if ( bp_is_active( 'friends' ) ) { 
  912. $users = friends_search_friends( $_GET['q'], bp_loggedin_user_id(), $limit, 1 ); 
  913.  
  914. // Keeping the bp_friends_autocomplete_list filter for backward compatibility 
  915. $users = apply_filters( 'bp_friends_autocomplete_list', $users, $_GET['q'], $limit ); 
  916.  
  917. if ( ! empty( $users['friends'] ) ) { 
  918. $user_ids = apply_filters( 'bp_friends_autocomplete_ids', $users['friends'], $_GET['q'], $limit ); 
  919.  
  920. if ( ! empty( $user_ids ) ) { 
  921. foreach ( $user_ids as $user_id ) { 
  922. $ud = get_userdata( $user_id ); 
  923. if ( ! $ud ) { 
  924. continue; 
  925.  
  926. if ( bp_is_username_compatibility_mode() ) { 
  927. // Sanitize for spaces 
  928. $username = urlencode( $ud->user_login ); 
  929. } else { 
  930. $username = $ud->user_nicename; 
  931.  
  932. // Note that the final line break acts as a delimiter for the 
  933. // autocomplete javascript and thus should not be removed 
  934. echo '<span id="link-' . esc_attr( $username ) . '" href="' . bp_core_get_user_domain( $user_id ) . '"></span>' . bp_core_fetch_avatar( array( 'item_id' => $user_id, 'type' => 'thumb', 'width' => 15, 'height' => 15, 'alt' => $ud->display_name ) ) . '  ' . bp_core_get_user_displayname( $user_id ) . ' (' . esc_html( $username ) . ')' . "\n"; 
  935.  
  936. exit; 
.