Advertisement
rdusnr

Untitled

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