/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.  
  233. if ( isset( $_POST['_wpnonce_activity_filter'] ) && wp_verify_nonce( wp_unslash( $_POST['_wpnonce_activity_filter'] ), 'activity_filter' ) ) { 
  234. bp_activity_clear_new_mentions( bp_loggedin_user_id() ); 
  235. break; 
  236. default: 
  237. $feed_url = home_url( bp_get_activity_root_slug() . '/feed/' ); 
  238. break; 
  239.  
  240. // Buffer the loop in the template to a var for JS to spit out. 
  241. ob_start(); 
  242. locate_template( array( 'activity/activity-loop.php' ), true ); 
  243. $result['contents'] = ob_get_contents(); 
  244. $result['feed_url'] = apply_filters( 'bp_dtheme_activity_feed_url', $feed_url, $scope ); 
  245. ob_end_clean(); 
  246.  
  247. exit( json_encode( $result ) ); 
  248.  
  249. /** 
  250. * Processes Activity updates received via a POST request. 
  251. * 
  252. * @return string HTML 
  253. * @since BuddyPress (1.2) 
  254. */ 
  255. function bp_dtheme_post_update() { 
  256. // Bail if not a POST action 
  257. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  258. return; 
  259.  
  260. // Check the nonce 
  261. check_admin_referer( 'post_update', '_wpnonce_post_update' ); 
  262.  
  263. if ( ! is_user_logged_in() ) 
  264. exit( '-1' ); 
  265.  
  266. if ( empty( $_POST['content'] ) ) 
  267. exit( '-1<div id="message" class="error"><p>' . __( 'Please enter some content to post.', 'buddypress' ) . '</p></div>' ); 
  268.  
  269. $activity_id = 0; 
  270. if ( empty( $_POST['object'] ) && bp_is_active( 'activity' ) ) { 
  271. $activity_id = bp_activity_post_update( array( 'content' => $_POST['content'], 'error_type' => 'wp_error' ) ); 
  272.  
  273. } elseif ( $_POST['object'] == 'groups' ) { 
  274. if ( ! empty( $_POST['item_id'] ) && bp_is_active( 'groups' ) ) 
  275. $activity_id = groups_post_update( array( 'content' => $_POST['content'], 'group_id' => $item_id, 'error_type' => 'wp_error' ) ); 
  276.  
  277. } else { 
  278. $activity_id = apply_filters( 'bp_activity_custom_update', $_POST['object'], $_POST['item_id'], $_POST['content'] ); 
  279.  
  280. if ( false === $activity_id ) { 
  281. exit( '-1<div id="message" class="error"><p>' . __( 'There was a problem posting your update, please try again.', 'buddypress' ) . '</p></div>' ); 
  282. } elseif ( is_wp_error( $activity_id ) && $activity_id->get_error_code() ) { 
  283. exit( '-1<div id="message" class="error bp-ajax-message"><p>' . $activity_id->get_error_message() . '</p></div>' ); 
  284.  
  285. if ( bp_has_activities ( 'include=' . $activity_id ) ) { 
  286. while ( bp_activities() ) { 
  287. bp_the_activity(); 
  288. locate_template( array( 'activity/entry.php' ), true ); 
  289.  
  290. exit; 
  291.  
  292. /** 
  293. * Posts new Activity comments received via a POST request. 
  294. * 
  295. * @global BP_Activity_Template $activities_template 
  296. * @return string HTML 
  297. * @since BuddyPress (1.2) 
  298. */ 
  299. function bp_dtheme_new_activity_comment() { 
  300. global $activities_template; 
  301.  
  302. // Bail if not a POST action 
  303. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  304. return; 
  305.  
  306. // Check the nonce 
  307. check_admin_referer( 'new_activity_comment', '_wpnonce_new_activity_comment' ); 
  308.  
  309. if ( ! is_user_logged_in() ) 
  310. exit( '-1' ); 
  311.  
  312. if ( empty( $_POST['content'] ) ) 
  313. exit( '-1<div id="message" class="error"><p>' . __( 'Please do not leave the comment area blank.', 'buddypress' ) . '</p></div>' ); 
  314.  
  315. if ( empty( $_POST['form_id'] ) || empty( $_POST['comment_id'] ) || ! is_numeric( $_POST['form_id'] ) || ! is_numeric( $_POST['comment_id'] ) ) 
  316. exit( '-1<div id="message" class="error"><p>' . __( 'There was an error posting that reply, please try again.', 'buddypress' ) . '</p></div>' ); 
  317.  
  318. $comment_id = bp_activity_new_comment( array( 
  319. 'activity_id' => $_POST['form_id'],  
  320. 'content' => $_POST['content'],  
  321. 'parent_id' => $_POST['comment_id'],  
  322. 'error_type' => 'wp_error' 
  323. ) ); 
  324.  
  325. if ( false === $comment_id ) { 
  326. exit( '-1<div id="message" class="error"><p>' . __( 'There was an error posting that reply, please try again.', 'buddypress' ) . '</p></div>' ); 
  327. } elseif ( is_wp_error( $comment_id ) ) { 
  328. exit( '-1<div id="message" class="error bp-ajax-message"><p>' . esc_html( $comment_id->get_error_message() ) . '</p></div>' ); 
  329.  
  330. // Load the new activity item into the $activities_template global 
  331. bp_has_activities( 'display_comments=stream&hide_spam=false&show_hidden=true&include=' . $comment_id ); 
  332.  
  333. // Swap the current comment with the activity item we just loaded 
  334. $activities_template->activity = new stdClass; 
  335. $activities_template->activity->id = $activities_template->activities[0]->item_id; 
  336. $activities_template->activity->current_comment = $activities_template->activities[0]; 
  337.  
  338. $template = locate_template( 'activity/comment.php', false, false ); 
  339.  
  340. /** 
  341. * Backward compatibility. In older versions of BP, the markup was 
  342. * generated in the PHP instead of a template. This ensures that 
  343. * older themes (which are not children of bp-default and won't 
  344. * have the new template) will still work. 
  345. */ 
  346. if ( empty( $template ) ) 
  347. $template = buddypress()->plugin_dir . '/bp-themes/bp-default/activity/comment.php'; 
  348.  
  349. load_template( $template, false ); 
  350.  
  351. unset( $activities_template ); 
  352. exit; 
  353.  
  354. /** 
  355. * Deletes an Activity item received via a POST request. 
  356. * 
  357. * @return mixed String on error, void on success 
  358. * @since BuddyPress (1.2) 
  359. */ 
  360. function bp_dtheme_delete_activity() { 
  361. // Bail if not a POST action 
  362. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  363. return; 
  364.  
  365. // Check the nonce 
  366. check_admin_referer( 'bp_activity_delete_link' ); 
  367.  
  368. if ( ! is_user_logged_in() ) 
  369. exit( '-1' ); 
  370.  
  371. if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 
  372. exit( '-1' ); 
  373.  
  374. $activity = new BP_Activity_Activity( (int) $_POST['id'] ); 
  375.  
  376. // Check access 
  377. if ( ! bp_activity_user_can_delete( $activity ) ) 
  378. exit( '-1' ); 
  379.  
  380. // Call the action before the delete so plugins can still fetch information about it 
  381. do_action( 'bp_activity_before_action_delete_activity', $activity->id, $activity->user_id ); 
  382.  
  383. if ( ! bp_activity_delete( array( 'id' => $activity->id, 'user_id' => $activity->user_id ) ) ) 
  384. exit( '-1<div id="message" class="error"><p>' . __( 'There was a problem when deleting. Please try again.', 'buddypress' ) . '</p></div>' ); 
  385.  
  386. do_action( 'bp_activity_action_delete_activity', $activity->id, $activity->user_id ); 
  387. exit; 
  388.  
  389. /** 
  390. * Deletes an Activity comment received via a POST request 
  391. * 
  392. * @return mixed String on error, void on success 
  393. * @since BuddyPress (1.2) 
  394. */ 
  395. function bp_dtheme_delete_activity_comment() { 
  396. // Bail if not a POST action 
  397. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  398. return; 
  399.  
  400. // Check the nonce 
  401. check_admin_referer( 'bp_activity_delete_link' ); 
  402.  
  403. if ( ! is_user_logged_in() ) 
  404. exit( '-1' ); 
  405.  
  406. $comment = new BP_Activity_Activity( $_POST['id'] ); 
  407.  
  408. // Check access 
  409. if ( ! bp_current_user_can( 'bp_moderate' ) && $comment->user_id != bp_loggedin_user_id() ) 
  410. exit( '-1' ); 
  411.  
  412. if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 
  413. exit( '-1' ); 
  414.  
  415. // Call the action before the delete so plugins can still fetch information about it 
  416. do_action( 'bp_activity_before_action_delete_activity', $_POST['id'], $comment->user_id ); 
  417.  
  418. if ( ! bp_activity_delete_comment( $comment->item_id, $comment->id ) ) 
  419. exit( '-1<div id="message" class="error"><p>' . __( 'There was a problem when deleting. Please try again.', 'buddypress' ) . '</p></div>' ); 
  420.  
  421. do_action( 'bp_activity_action_delete_activity', $_POST['id'], $comment->user_id ); 
  422. exit; 
  423.  
  424. /** 
  425. * AJAX spam an activity item or comment 
  426. * 
  427. * @global BuddyPress $bp The one true BuddyPress instance 
  428. * @return mixed String on error, void on success 
  429. * @since BuddyPress (1.6) 
  430. */ 
  431. function bp_dtheme_spam_activity() { 
  432. global $bp; 
  433.  
  434. // Bail if not a POST action 
  435. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  436. return; 
  437.  
  438. // Check that user is logged in, Activity Streams are enabled, and Akismet is present. 
  439. if ( ! is_user_logged_in() || ! bp_is_active( 'activity' ) || empty( $bp->activity->akismet ) ) 
  440. exit( '-1' ); 
  441.  
  442. // Check an item ID was passed 
  443. if ( empty( $_POST['id'] ) || ! is_numeric( $_POST['id'] ) ) 
  444. exit( '-1' ); 
  445.  
  446. // Is the current user allowed to spam items? 
  447. if ( ! bp_activity_user_can_mark_spam() ) 
  448. exit( '-1' ); 
  449.  
  450. // Load up the activity item 
  451. $activity = new BP_Activity_Activity( (int) $_POST['id'] ); 
  452. if ( empty( $activity->component ) ) 
  453. exit( '-1' ); 
  454.  
  455. // Check nonce 
  456. check_admin_referer( 'bp_activity_akismet_spam_' . $activity->id ); 
  457.  
  458. // Call an action before the spamming so plugins can modify things if they want to 
  459. do_action( 'bp_activity_before_action_spam_activity', $activity->id, $activity ); 
  460.  
  461. // Mark as spam 
  462. bp_activity_mark_as_spam( $activity ); 
  463. $activity->save(); 
  464.  
  465. do_action( 'bp_activity_action_spam_activity', $activity->id, $activity->user_id ); 
  466. exit; 
  467.  
  468. /** 
  469. * Mark an activity as a favourite via a POST request. 
  470. * 
  471. * @return string HTML 
  472. * @since BuddyPress (1.2) 
  473. */ 
  474. function bp_dtheme_mark_activity_favorite() { 
  475. // Bail if not a POST action 
  476. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  477. return; 
  478.  
  479. if ( ! isset( $_POST['nonce'] ) ) { 
  480. return; 
  481.  
  482. // Either the 'mark' or 'unmark' nonce is accepted, for backward compatibility. 
  483. $nonce = wp_unslash( $_POST['nonce'] ); 
  484. if ( ! wp_verify_nonce( $nonce, 'mark_favorite' ) && ! wp_verify_nonce( $nonce, 'unmark_favorite' ) ) { 
  485. return; 
  486.  
  487. if ( bp_activity_add_user_favorite( $_POST['id'] ) ) 
  488. _e( 'Remove Favorite', 'buddypress' ); 
  489. else 
  490. _e( 'Favorite', 'buddypress' ); 
  491.  
  492. exit; 
  493.  
  494. /** 
  495. * Un-favourite an activity via a POST request. 
  496. * 
  497. * @return string HTML 
  498. * @since BuddyPress (1.2) 
  499. */ 
  500. function bp_dtheme_unmark_activity_favorite() { 
  501. // Bail if not a POST action 
  502. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  503. return; 
  504.  
  505. if ( ! isset( $_POST['nonce'] ) ) { 
  506. return; 
  507.  
  508. // Either the 'mark' or 'unmark' nonce is accepted, for backward compatibility. 
  509. $nonce = wp_unslash( $_POST['nonce'] ); 
  510. if ( ! wp_verify_nonce( $nonce, 'mark_favorite' ) && ! wp_verify_nonce( $nonce, 'unmark_favorite' ) ) { 
  511. return; 
  512.  
  513. if ( bp_activity_remove_user_favorite( $_POST['id'] ) ) 
  514. _e( 'Favorite', 'buddypress' ); 
  515. else 
  516. _e( 'Remove Favorite', 'buddypress' ); 
  517.  
  518. exit; 
  519.  
  520. /** 
  521. * Fetches full an activity's full, non-excerpted content via a POST request. 
  522. * Used for the 'Read More' link on long activity items. 
  523. * 
  524. * @return string HTML 
  525. * @since BuddyPress (1.5) 
  526. */ 
  527. function bp_dtheme_get_single_activity_content() { 
  528. // Bail if not a POST action 
  529. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  530. return; 
  531.  
  532. $activity_array = bp_activity_get_specific( array( 
  533. 'activity_ids' => $_POST['activity_id'],  
  534. 'display_comments' => 'stream' 
  535. ) ); 
  536.  
  537. $activity = ! empty( $activity_array['activities'][0] ) ? $activity_array['activities'][0] : false; 
  538.  
  539. if ( empty( $activity ) ) 
  540. exit; // @todo: error? 
  541.  
  542. do_action_ref_array( 'bp_dtheme_get_single_activity_content', array( &$activity ) ); 
  543.  
  544. // Activity content retrieved through AJAX should run through normal filters, but not be truncated 
  545. remove_filter( 'bp_get_activity_content_body', 'bp_activity_truncate_entry', 5 ); 
  546. $content = apply_filters( 'bp_get_activity_content_body', $activity->content ); 
  547.  
  548. exit( $content ); 
  549.  
  550. /** 
  551. * Invites a friend to join a group via a POST request. 
  552. * 
  553. * @since BuddyPress (1.2) 
  554. * @todo Audit return types 
  555. */ 
  556. function bp_dtheme_ajax_invite_user() { 
  557. // Bail if not a POST action 
  558. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  559. return; 
  560.  
  561. check_ajax_referer( 'groups_invite_uninvite_user' ); 
  562.  
  563. if ( ! $_POST['friend_id'] || ! $_POST['friend_action'] || ! $_POST['group_id'] ) 
  564. return; 
  565.  
  566. if ( ! bp_groups_user_can_send_invites( $_POST['group_id'] ) ) 
  567. return; 
  568.  
  569. if ( ! friends_check_friendship( bp_loggedin_user_id(), $_POST['friend_id'] ) ) 
  570. return; 
  571.  
  572. $group_id = (int) $_POST['group_id']; 
  573. $friend_id = (int) $_POST['friend_id']; 
  574.  
  575. if ( 'invite' == $_POST['friend_action'] ) { 
  576. $group = groups_get_group( $group_id ); 
  577.  
  578. // Users who have previously requested membership do not need 
  579. // another invitation created for them 
  580. if ( BP_Groups_Member::check_for_membership_request( $friend_id, $group_id ) ) { 
  581. $user_status = 'is_pending'; 
  582.  
  583. // Create the user invitation 
  584. } else if ( groups_invite_user( array( 'user_id' => $friend_id, 'group_id' => $group_id ) ) ) { 
  585. $user_status = 'is_invited'; 
  586.  
  587. // Miscellaneous failure 
  588. } else { 
  589. return; 
  590.  
  591. $user = new BP_Core_User( $_POST['friend_id'] ); 
  592.  
  593. echo '<li id="uid-' . $user->id . '">'; 
  594. echo $user->avatar_thumb; 
  595. echo '<h4>' . $user->user_link . '</h4>'; 
  596. echo '<span class="activity">' . esc_attr( $user->last_active ) . '</span>'; 
  597. echo '<div class="action"> 
  598. <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> 
  599. </div>'; 
  600.  
  601. if ( 'is_pending' == $user_status ) { 
  602. 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>'; 
  603.  
  604. echo '</li>'; 
  605. exit; 
  606.  
  607. } elseif ( 'uninvite' == $_POST['friend_action'] ) { 
  608. // Users who have previously requested membership should not 
  609. // have their requests deleted on the "uninvite" action 
  610. if ( BP_Groups_Member::check_for_membership_request( $friend_id, $group_id ) ) { 
  611. return; 
  612.  
  613. // Remove the unsent invitation 
  614. if ( ! groups_uninvite_user( $friend_id, $group_id ) ) { 
  615. return; 
  616.  
  617. exit; 
  618.  
  619. } else { 
  620. return; 
  621.  
  622. /** 
  623. * Friend/un-friend a user via a POST request. 
  624. * 
  625. * @return string HTML 
  626. * @since BuddyPress (1.2) 
  627. */ 
  628. function bp_dtheme_ajax_addremove_friend() { 
  629. // Bail if not a POST action 
  630. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  631. return; 
  632.  
  633. // Cast fid as an integer 
  634. $friend_id = (int) $_POST['fid']; 
  635.  
  636. // Trying to cancel friendship 
  637. if ( 'is_friend' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  638. check_ajax_referer( 'friends_remove_friend' ); 
  639.  
  640. if ( ! friends_remove_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  641. echo __( 'Friendship could not be canceled.', 'buddypress' ); 
  642. } else { 
  643. 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>'; 
  644.  
  645. // Trying to request friendship 
  646. } elseif ( 'not_friends' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  647. check_ajax_referer( 'friends_add_friend' ); 
  648.  
  649. if ( ! friends_add_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  650. echo __(' Friendship could not be requested.', 'buddypress' ); 
  651. } else { 
  652. 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>'; 
  653.  
  654. // Trying to cancel pending request 
  655. } elseif ( 'pending' == BP_Friends_Friendship::check_is_friend( bp_loggedin_user_id(), $friend_id ) ) { 
  656. check_ajax_referer( 'friends_withdraw_friendship' ); 
  657.  
  658. if ( friends_withdraw_friendship( bp_loggedin_user_id(), $friend_id ) ) { 
  659. 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>'; 
  660. } else { 
  661. echo __("Friendship request could not be cancelled.", 'buddypress'); 
  662.  
  663. // Request already pending 
  664. } else { 
  665. echo __( 'Request Pending', 'buddypress' ); 
  666.  
  667. exit; 
  668.  
  669. /** 
  670. * Accept 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_accept_friendship() { 
  676. // Bail if not a POST action 
  677. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  678. return; 
  679.  
  680. check_admin_referer( 'friends_accept_friendship' ); 
  681.  
  682. if ( ! friends_accept_friendship( (int) $_POST['id'] ) ) 
  683. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem accepting that request. Please try again.', 'buddypress' ) . '</p></div>'; 
  684.  
  685. exit; 
  686.  
  687. /** 
  688. * Reject a user friendship request via a POST request. 
  689. * 
  690. * @return mixed String on error, void on success 
  691. * @since BuddyPress (1.2) 
  692. */ 
  693. function bp_dtheme_ajax_reject_friendship() { 
  694. // Bail if not a POST action 
  695. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  696. return; 
  697.  
  698. check_admin_referer( 'friends_reject_friendship' ); 
  699.  
  700. if ( ! friends_reject_friendship( (int) $_POST['id'] ) ) 
  701. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem rejecting that request. Please try again.', 'buddypress' ) . '</p></div>'; 
  702.  
  703. exit; 
  704.  
  705. /** 
  706. * Join or leave a group when clicking the "join/leave" button via a POST request. 
  707. * 
  708. * @return string HTML 
  709. * @since BuddyPress (1.2) 
  710. */ 
  711. function bp_dtheme_ajax_joinleave_group() { 
  712. // Bail if not a POST action 
  713. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  714. return; 
  715.  
  716. // Cast gid as integer 
  717. $group_id = (int) $_POST['gid']; 
  718.  
  719. if ( groups_is_user_banned( bp_loggedin_user_id(), $group_id ) ) 
  720. return; 
  721.  
  722. if ( ! $group = groups_get_group( array( 'group_id' => $group_id ) ) ) 
  723. return; 
  724.  
  725. if ( ! groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) { 
  726. if ( 'public' == $group->status ) { 
  727. check_ajax_referer( 'groups_join_group' ); 
  728.  
  729. if ( ! groups_join_group( $group->id ) ) { 
  730. _e( 'Error joining group', 'buddypress' ); 
  731. } else { 
  732. 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>'; 
  733.  
  734. } elseif ( 'private' == $group->status ) { 
  735.  
  736. // If the user has already been invited, then this is 
  737. // an Accept Invitation button 
  738. if ( groups_check_user_has_invite( bp_loggedin_user_id(), $group->id ) ) { 
  739. check_ajax_referer( 'groups_accept_invite' ); 
  740.  
  741. if ( ! groups_accept_invite( bp_loggedin_user_id(), $group->id ) ) { 
  742. _e( 'Error requesting membership', 'buddypress' ); 
  743. } else { 
  744. 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>'; 
  745.  
  746. // Otherwise, it's a Request Membership button 
  747. } else { 
  748. check_ajax_referer( 'groups_request_membership' ); 
  749.  
  750. if ( ! groups_send_membership_request( bp_loggedin_user_id(), $group->id ) ) { 
  751. _e( 'Error requesting membership', 'buddypress' ); 
  752. } else { 
  753. 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>'; 
  754.  
  755. } else { 
  756. check_ajax_referer( 'groups_leave_group' ); 
  757.  
  758. if ( ! groups_leave_group( $group->id ) ) { 
  759. _e( 'Error leaving group', 'buddypress' ); 
  760. } elseif ( 'public' == $group->status ) { 
  761. 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>'; 
  762. } elseif ( 'private' == $group->status ) { 
  763. 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>'; 
  764.  
  765. exit; 
  766.  
  767. /** 
  768. * Close and keep closed site wide notices from an admin in the sidebar, via a POST request. 
  769. * 
  770. * @return mixed String on error, void on success 
  771. * @since BuddyPress (1.2) 
  772. */ 
  773. function bp_dtheme_ajax_close_notice() { 
  774. // Bail if not a POST action 
  775. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  776. return; 
  777.  
  778. $nonce_check = isset( $_POST['nonce'] ) && wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'bp_messages_close_notice' ); 
  779.  
  780. if ( ! $nonce_check || ! isset( $_POST['notice_id'] ) ) { 
  781. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem closing the notice.', 'buddypress' ) . '</p></div>'; 
  782.  
  783. } else { 
  784. $user_id = get_current_user_id(); 
  785. $notice_ids = bp_get_user_meta( $user_id, 'closed_notices', true ); 
  786. $notice_ids[] = (int) $_POST['notice_id']; 
  787.  
  788. bp_update_user_meta( $user_id, 'closed_notices', $notice_ids ); 
  789.  
  790. exit; 
  791.  
  792. /** 
  793. * Send a private message reply to a thread via a POST request. 
  794. * 
  795. * @return string HTML 
  796. * @since BuddyPress (1.2) 
  797. */ 
  798. function bp_dtheme_ajax_messages_send_reply() { 
  799. // Bail if not a POST action 
  800. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  801. return; 
  802.  
  803. check_ajax_referer( 'messages_send_message' ); 
  804.  
  805. $result = messages_new_message( array( 'thread_id' => (int) $_REQUEST['thread_id'], 'content' => $_REQUEST['content'] ) ); 
  806.  
  807. if ( $result ) { ?> 
  808. <div class="message-box new-message"> 
  809. <div class="message-metadata"> 
  810. <?php do_action( 'bp_before_message_meta' ); ?> 
  811. <?php echo bp_loggedin_user_avatar( 'type=thumb&width=30&height=30' ); ?> 
  812.  
  813. <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> 
  814.  
  815. <?php do_action( 'bp_after_message_meta' ); ?> 
  816. </div> 
  817.  
  818. <?php do_action( 'bp_before_message_content' ); ?> 
  819.  
  820. <div class="message-content"> 
  821. <?php echo stripslashes( apply_filters( 'bp_get_the_thread_message_content', $_REQUEST['content'] ) ); ?> 
  822. </div> 
  823.  
  824. <?php do_action( 'bp_after_message_content' ); ?> 
  825.  
  826. <div class="clear"></div> 
  827. </div> 
  828. <?php 
  829. } else { 
  830. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem sending that reply. Please try again.', 'buddypress' ) . '</p></div>'; 
  831.  
  832. exit; 
  833.  
  834. /** 
  835. * Mark a private message as unread in your inbox via a POST request. 
  836. * 
  837. * @return mixed String on error, void on success 
  838. * @since BuddyPress (1.2) 
  839. */ 
  840. function bp_dtheme_ajax_message_markunread() { 
  841. // Bail if not a POST action 
  842. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  843. return; 
  844.  
  845. $nonce_check = isset( $_POST['nonce'] ) && wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'bp_messages_mark_messages_unread' ); 
  846.  
  847. if ( ! $nonce_check || ! isset( $_POST['thread_ids'] ) ) { 
  848. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem marking messages as unread.', '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_unread( (int) $thread_ids[$i] ); 
  855.  
  856. exit; 
  857.  
  858. /** 
  859. * Mark a private message as read in your inbox via a POST request. 
  860. * 
  861. * @return mixed String on error, void on success 
  862. * @since BuddyPress (1.2) 
  863. */ 
  864. function bp_dtheme_ajax_message_markread() { 
  865. // Bail if not a POST action 
  866. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  867. return; 
  868.  
  869. $nonce_check = isset( $_POST['nonce'] ) && wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'bp_messages_mark_messages_read' ); 
  870.  
  871. if ( ! $nonce_check || ! isset( $_POST['thread_ids'] ) ) { 
  872. echo "-1<div id='message' class='error'><p>" . __('There was a problem marking messages as read.', 'buddypress' ) . '</p></div>'; 
  873.  
  874. } else { 
  875. $thread_ids = explode( ', ', $_POST['thread_ids'] ); 
  876.  
  877. for ( $i = 0, $count = count( $thread_ids ); $i < $count; ++$i ) { 
  878. BP_Messages_Thread::mark_as_read( (int) $thread_ids[$i] ); 
  879.  
  880. exit; 
  881.  
  882. /** 
  883. * Delete a private message(s) in your inbox via a POST request. 
  884. * 
  885. * @return string HTML 
  886. * @since BuddyPress (1.2) 
  887. */ 
  888. function bp_dtheme_ajax_messages_delete() { 
  889. // Bail if not a POST action 
  890. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  891. return; 
  892.  
  893. $nonce_check = isset( $_POST['nonce'] ) && wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'bp_messages_delete_selected' ); 
  894.  
  895. if ( ! $nonce_check || ! isset($_POST['thread_ids']) ) { 
  896. echo "-1<div id='message' class='error'><p>" . __( 'There was a problem deleting messages.', 'buddypress' ) . '</p></div>'; 
  897.  
  898. } else { 
  899. $thread_ids = explode( ', ', $_POST['thread_ids'] ); 
  900.  
  901. for ( $i = 0, $count = count( $thread_ids ); $i < $count; ++$i ) { 
  902. BP_Messages_Thread::delete( (int) $thread_ids[$i] ); 
  903.  
  904. _e( 'Messages deleted.', 'buddypress' ); 
  905.  
  906. exit; 
  907.  
  908. /** 
  909. * AJAX handler for autocomplete. Displays friends only, unless BP_MESSAGES_AUTOCOMPLETE_ALL is defined. 
  910. * 
  911. * @return string HTML 
  912. * @since BuddyPress (1.2) 
  913. */ 
  914. function bp_dtheme_ajax_messages_autocomplete_results() { 
  915.  
  916. // Include everyone in the autocomplete, or just friends? 
  917. if ( bp_is_current_component( bp_get_messages_slug() ) ) 
  918. $autocomplete_all = buddypress()->messages->autocomplete_all; 
  919.  
  920. $pag_page = 1; 
  921. $limit = (int) $_GET['limit'] ? $_GET['limit'] : apply_filters( 'bp_autocomplete_max_results', 10 ); 
  922.  
  923. // Get the user ids based on the search terms 
  924. if ( ! empty( $autocomplete_all ) ) { 
  925. $users = BP_Core_User::search_users( $_GET['q'], $limit, $pag_page ); 
  926.  
  927. if ( ! empty( $users['users'] ) ) { 
  928. // Build an array with the correct format 
  929. $user_ids = array(); 
  930. foreach( $users['users'] as $user ) { 
  931. if ( $user->id != bp_loggedin_user_id() ) { 
  932. $user_ids[] = $user->id; 
  933.  
  934. $user_ids = apply_filters( 'bp_core_autocomplete_ids', $user_ids, $_GET['q'], $limit ); 
  935.  
  936. } else { 
  937. if ( bp_is_active( 'friends' ) ) { 
  938. $users = friends_search_friends( $_GET['q'], bp_loggedin_user_id(), $limit, 1 ); 
  939.  
  940. // Keeping the bp_friends_autocomplete_list filter for backward compatibility 
  941. $users = apply_filters( 'bp_friends_autocomplete_list', $users, $_GET['q'], $limit ); 
  942.  
  943. if ( ! empty( $users['friends'] ) ) { 
  944. $user_ids = apply_filters( 'bp_friends_autocomplete_ids', $users['friends'], $_GET['q'], $limit ); 
  945.  
  946. if ( ! empty( $user_ids ) ) { 
  947. foreach ( $user_ids as $user_id ) { 
  948. $ud = get_userdata( $user_id ); 
  949. if ( ! $ud ) { 
  950. continue; 
  951.  
  952. if ( bp_is_username_compatibility_mode() ) { 
  953. // Sanitize for spaces 
  954. $username = urlencode( $ud->user_login ); 
  955. } else { 
  956. $username = $ud->user_nicename; 
  957.  
  958. // Note that the final line break acts as a delimiter for the 
  959. // autocomplete javascript and thus should not be removed 
  960. 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"; 
  961.  
  962. exit; 
.