PluginProbe
bbPress / trunk
bbPress vtrunk
2.6.19 2.6.18 2.6.17 trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 All 74 releases
bbpress / includes / extend / buddypress / groups.php

groups.php in bbPress trunk, at includes/extend/buddypress/groups.php

2,095 lines 57.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * bbPress BuddyPress Group Extension Class.
5 *
6 * This file is responsible for connecting bbPress to the BuddyPress Groups
7 * Component. It's a great example of how to perform both simple and advanced
8 * techniques to manipulate the default output provided by both.
9 *
10 * @package bbPress
11 * @subpackage BuddyPress
12 */
13
14 // Exit if accessed directly
15 defined( 'ABSPATH' ) || exit;
16
17 if ( ! class_exists( 'BBP_Forums_Group_Extension' ) && class_exists( 'BP_Group_Extension' ) ) :
18 /**
19 * Loads Group Extension for Forums Component.
20 *
21 * @since 2.1.0 bbPress (r3552)
22 *
23 * @package bbPress
24 * @subpackage BuddyPress
25 */
26 class BBP_Forums_Group_Extension extends BP_Group_Extension {
27
28 /** Methods ***************************************************************/
29
30 /**
31 * Setup bbPress group extension variables.
32 *
33 * @since 2.1.0 bbPress (r3552)
34 */
35 public function __construct() {
36 $this->setup_variables();
37 $this->setup_actions();
38 $this->setup_filters();
39 $this->maybe_unset_forum_menu();
40 $this->fully_loaded();
41 }
42
43 /**
44 * Setup the group forums class variables.
45 *
46 * @since 2.3.0 bbPress (r4553)
47 */
48 private function setup_variables() {
49
50 // Component Name
51 $this->name = esc_html__( 'Forum', 'bbpress' );
52 $this->nav_item_name = esc_html__( 'Forum', 'bbpress' );
53
54 // Component slugs (hardcoded to match bbPress 1.x functionality)
55 $this->slug = 'forum';
56 $this->topic_slug = 'topic';
57 $this->reply_slug = 'reply';
58
59 // Forum component is visible
60 $this->visibility = 'public';
61
62 // Set positions towards end
63 $this->create_step_position = 15;
64 $this->nav_item_position = 10;
65
66 // Allow create step and show in nav
67 $this->enable_create_step = true;
68 $this->enable_nav_item = true;
69 $this->enable_edit_item = true;
70
71 // Template file to load, and action to hook display on to
72 $this->template_file = 'groups/single/plugins';
73 $this->display_hook = 'bp_template_content';
74 }
75
76 /**
77 * Setup the group forums class actions.
78 *
79 * @since 2.3.0 bbPress (r4553)
80 */
81 private function setup_actions() {
82
83 // Possibly redirect
84 add_action( 'bbp_template_redirect', array( $this, 'redirect_canonical' ) );
85
86 // Remove group forum cap map when view is done
87 add_action( 'bbp_after_group_forum_display', array( $this, 'remove_group_forum_meta_cap_map' ) );
88
89 // Validate group IDs when editing topics & replies
90 add_action( 'bbp_edit_topic_pre_extras', array( $this, 'validate_topic_forum_id' ) );
91 add_action( 'bbp_edit_reply_pre_extras', array( $this, 'validate_reply_to_id' ) );
92
93 // Check if group-forum attributes should be changed
94 add_action( 'groups_group_after_save', array( $this, 'update_group_forum' ) );
95
96 // bbPress needs to listen to BuddyPress group deletion
97 add_action( 'groups_before_delete_group', array( $this, 'disconnect_forum_from_group' ) );
98
99 // Adds a bbPress meta-box to the new BuddyPress Group Admin UI
100 add_action( 'bp_groups_admin_meta_boxes', array( $this, 'group_admin_ui_edit_screen' ) );
101
102 // Saves the bbPress options if they come from the BuddyPress Group Admin UI
103 add_action( 'bp_group_admin_edit_after', array( $this, 'edit_screen_save' ) );
104
105 // Adds a hidden input value to the "Group Settings" page
106 add_action( 'bp_before_group_settings_admin', array( $this, 'group_settings_hidden_field' ) );
107 }
108
109 /**
110 * Setup the group forums class filters.
111 *
112 * @since 2.3.0 bbPress (r4553)
113 */
114 private function setup_filters() {
115
116 // Group forum pagination
117 add_filter( 'bbp_topic_pagination', array( $this, 'topic_pagination' ) );
118 add_filter( 'bbp_replies_pagination', array( $this, 'replies_pagination' ) );
119 add_filter( 'bbp_get_global_object', array( $this, 'rewrite_pagination' ), 10, 2 );
120
121 // Tweak the redirect field
122 add_filter( 'bbp_new_topic_redirect_to', array( $this, 'new_topic_redirect_to' ), 10, 3 );
123 add_filter( 'bbp_new_reply_redirect_to', array( $this, 'new_reply_redirect_to' ), 10, 3 );
124
125 // Map forum/topic/reply permalinks to their groups
126 add_filter( 'bbp_get_forum_permalink', array( $this, 'map_forum_permalink_to_group' ), 10, 2 );
127 add_filter( 'bbp_get_topic_permalink', array( $this, 'map_topic_permalink_to_group' ), 10, 2 );
128 add_filter( 'bbp_get_reply_permalink', array( $this, 'map_reply_permalink_to_group' ), 10, 2 );
129
130 // Map reply edit links to their groups
131 add_filter( 'bbp_get_reply_edit_url', array( $this, 'map_reply_edit_url_to_group' ), 10, 2 );
132
133 // Map assorted template function permalinks
134 add_filter( 'post_link', array( $this, 'post_link' ), 10, 2 );
135 add_filter( 'page_link', array( $this, 'page_link' ), 10, 2 );
136 add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
137
138 // Map group forum activity items to groups
139 add_filter( 'bbp_before_record_activity_parse_args', array( $this, 'map_activity_to_group' ) );
140
141 // Allow group members to receive group forum notifications
142 add_filter( 'bbp_subscription_user_can_view_forum', array( $this, 'subscription_user_can_view_forum' ), 10, 3 );
143
144 // Restrict private and hidden group forums outside of group requests
145 add_filter( 'bbp_map_meta_caps', array( $this, 'map_group_forum_read_meta_caps' ), 20, 4 );
146 add_filter( 'bbp_get_excluded_forum_ids', array( $this, 'exclude_group_forum_ids' ), 20 );
147
148 /** Caps **************************************************************/
149
150 // Only add these filters if inside a group forum
151 if ( bp_is_single_item() && bp_is_group() && bp_is_current_action( $this->slug ) ) {
152
153 // Ensure bbp_is_single_forum() returns true on group forums.
154 add_filter( 'bbp_is_single_forum', array( $this, 'is_single_forum' ) );
155
156 // Ensure bbp_is_single_topic() returns true on group forum topics.
157 add_filter( 'bbp_is_single_topic', array( $this, 'is_single_topic' ) );
158
159 // Allow group member to view private/hidden forums
160 add_filter( 'bbp_map_meta_caps', array( $this, 'map_group_forum_meta_caps' ), 10, 4 );
161
162 // Group member permissions to view the topic and reply forms
163 add_filter( 'bbp_current_user_can_access_create_topic_form', array( $this, 'form_permissions' ) );
164 add_filter( 'bbp_current_user_can_access_create_reply_form', array( $this, 'form_permissions' ) );
165 }
166 }
167
168 /**
169 * Check whether a user can view a private or hidden group forum.
170 *
171 * @since 2.7.0 bbPress (r7495)
172 *
173 * @param int $user_id User ID.
174 * @param int $forum_id Forum ID.
175 * @return bool|null Whether the user can view the group forum, or null when
176 * the forum is not a restricted group forum.
177 */
178 public function user_can_view_group_forum( $user_id = 0, $forum_id = 0 ) {
179 $user_id = bbp_get_user_id( $user_id, false, false );
180 $forum_id = bbp_get_forum_id( $forum_id );
181 $group_ids = bbp_get_forum_group_ids( $forum_id );
182
183 // Keep normal bbPress permissions for other forums
184 if ( empty( $group_ids ) || ! bbp_is_forum_restricted( $forum_id, false ) ) {
185 return null;
186 }
187
188 // Preserve access for global and per-forum moderators
189 if ( bbp_is_user_forum_moderator( $user_id, $forum_id ) ) {
190 return true;
191 }
192
193 // Allow current, non-banned members of any attached group
194 foreach ( $group_ids as $group_id ) {
195 if ( false === groups_is_user_banned( $user_id, $group_id ) && false !== groups_is_user_member( $user_id, $group_id ) ) {
196 return true;
197 }
198 }
199
200 return false;
201 }
202
203 /**
204 * Map read access for private and hidden group forums in every request.
205 *
206 * @since 2.7.0 bbPress (r7495)
207 *
208 * @param array $caps Capabilities for the meta capability.
209 * @param string $cap Capability name.
210 * @param int $user_id User ID.
211 * @param array $args Arguments.
212 * @return array Actual capabilities for the meta capability.
213 */
214 public function map_group_forum_read_meta_caps( $caps = array(), $cap = '', $user_id = 0, $args = array() ) {
215 if ( ( 'read_forum' !== $cap ) || empty( $args[0] ) ) {
216 return $caps;
217 }
218
219 // Preserve an earlier hard denial, including inactive users and
220 // restricted ancestors the user cannot read
221 if ( in_array( 'do_not_allow', $caps, true ) ) {
222 return $caps;
223 }
224
225 $can_view = $this->user_can_view_group_forum( $user_id, $args[0] );
226
227 if ( null !== $can_view ) {
228 $caps = $can_view
229 ? array( 'participate' )
230 : array( 'do_not_allow' );
231 }
232
233 return $caps;
234 }
235
236 /**
237 * Exclude private and hidden group forums a user cannot view.
238 *
239 * @since 2.7.0 bbPress (r7495)
240 * @since 2.6.19 bbPress (r7677) Exclude unreadable descendants.
241 *
242 * @param array $forum_ids Forum IDs already excluded.
243 * @return array Forum IDs the user cannot view.
244 */
245 public function exclude_group_forum_ids( $forum_ids ) {
246 $user_id = bbp_get_current_user_id();
247 $restricted = array_merge( bbp_get_private_forum_ids(), bbp_get_hidden_forum_ids() );
248 $restricted = wp_parse_id_list( $restricted );
249
250 foreach ( $restricted as $forum_id ) {
251 // Skip forums that are not attached to groups
252 if ( empty( bbp_get_forum_group_ids( $forum_id ) ) ) {
253 continue;
254 }
255
256 if ( ! user_can( $user_id, 'read_forum', $forum_id ) ) {
257 // Exclude descendants too, except those this user can read.
258 $parents = array( $forum_id );
259 $seen = array( $forum_id => true );
260 $readable = array();
261 $forum_ids[] = $forum_id;
262
263 while ( ! empty( $parents ) ) {
264 $parent_id = array_shift( $parents );
265
266 foreach ( bbp_forum_query_all_subforum_ids( $parent_id ) as $child_id ) {
267 $child_id = (int) $child_id;
268
269 if ( isset( $seen[ $child_id ] ) ) {
270 continue;
271 }
272
273 $seen[ $child_id ] = true;
274 $parents[] = $child_id;
275
276 if ( user_can( $user_id, 'read_forum', $child_id ) ) {
277 $readable[] = $child_id;
278 } else {
279 $forum_ids[] = $child_id;
280 }
281 }
282 }
283
284 $forum_ids = array_diff( $forum_ids, $readable );
285 continue;
286 }
287
288 // Include readable descendants that inherited this restriction
289 $readable = array( $forum_id );
290 foreach ( $forum_ids as $excluded_id ) {
291 if ( in_array( $forum_id, bbp_get_forum_ancestors( $excluded_id ), true ) ) {
292 $readable[] = $excluded_id;
293 }
294 }
295
296 foreach ( $readable as $readable_id ) {
297 if ( user_can( $user_id, 'read_forum', $readable_id ) ) {
298 $forum_ids = array_diff( $forum_ids, array( $readable_id ) );
299 }
300 }
301 }
302
303 return wp_parse_id_list( $forum_ids );
304 }
305
306 /**
307 * Allow a group member to receive notifications from an attached forum.
308 *
309 * Unlike the request-specific capability mapping, this check accepts an
310 * explicit user ID so it can validate subscription recipients.
311 *
312 * @since 2.6.17 bbPress (r7493)
313 *
314 * @param bool $retval Whether the user can view the forum.
315 * @param int $user_id User ID.
316 * @param int $forum_id Forum ID.
317 * @return bool Whether the user can view the forum.
318 */
319 public function subscription_user_can_view_forum( $retval, $user_id, $forum_id ) {
320 $can_view = $this->user_can_view_group_forum( $user_id, $forum_id );
321
322 return ( null === $can_view ) ? $retval : ( $retval && $can_view );
323 }
324
325 /**
326 * Allow the variables, actions, and filters to be modified by third party
327 * plugins and themes.
328 *
329 * @since 2.6.0 bbPress (r6808)
330 */
331 private function fully_loaded() {
332 do_action_ref_array( 'bbp_buddypress_groups_loaded', array( $this ) );
333 }
334
335 /**
336 * Ensure that bbp_is_single_forum() returns true on group forum pages.
337 *
338 * @see https://bbpress.trac.wordpress.org/ticket/2974
339 *
340 * @since 2.6.0 bbPress (r6367)
341 *
342 * @param bool $retval Current boolean.
343 * @return bool
344 */
345 public function is_single_forum( $retval = false ) {
346
347 // Additional BuddyPress specific single-forum conditionals
348 if ( ( false === $retval ) && ! bp_is_action_variable( $this->topic_slug, 0 ) ) {
349 $retval = true;
350 }
351
352 return $retval;
353 }
354
355 /**
356 * Ensure that bbp_is_single_topic() returns true on group forum topic pages.
357 *
358 * @see https://bbpress.trac.wordpress.org/ticket/2974
359 *
360 * @since 2.6.0 bbPress (r6220)
361 *
362 * @param bool $retval Current boolean.
363 * @return bool
364 */
365 public function is_single_topic( $retval = false ) {
366
367 // Additional BuddyPress specific single-topic conditionals
368 if ( ( false === $retval ) && bp_is_action_variable( $this->topic_slug, 0 ) && bp_action_variable( 1 ) ) {
369 $retval = true;
370 }
371
372 return $retval;
373 }
374
375 /**
376 * The primary display function for group forums.
377 *
378 * @since 2.1.0 bbPress (r3552)
379 *
380 * @param int $group_id ID of the current group. Available only on BP 2.2+.
381 */
382 public function display( $group_id = null ) {
383
384 // Prevent Topic Parent from appearing
385 add_action( 'bbp_theme_before_topic_form_forum', array( $this, 'ob_start' ) );
386 add_action( 'bbp_theme_after_topic_form_forum', array( $this, 'ob_end_clean' ) );
387 add_action( 'bbp_theme_after_topic_form_forum', array( $this, 'topic_parent' ) );
388
389 // Prevent Forum Parent from appearing
390 add_action( 'bbp_theme_before_forum_form_parent', array( $this, 'ob_start' ) );
391 add_action( 'bbp_theme_after_forum_form_parent', array( $this, 'ob_end_clean' ) );
392 add_action( 'bbp_theme_after_forum_form_parent', array( $this, 'forum_parent' ) );
393
394 // Hide breadcrumb
395 add_filter( 'bbp_no_breadcrumb', '__return_true' );
396
397 $this->display_forums( 0 );
398 }
399
400 /**
401 * Maybe unset the group forum nav item if group does not have a forum.
402 *
403 * @since 2.3.0 bbPress (r4553)
404 *
405 * @return If not viewing a single group.
406 */
407 public function maybe_unset_forum_menu() {
408
409 // Bail if not viewing a single group
410 if ( ! bp_is_group() ) {
411 return;
412 }
413
414 // Are forums enabled for this group?
415 $checked = bp_get_new_group_enable_forum() || groups_get_groupmeta( bp_get_new_group_id(), 'forum_id' );
416
417 // Tweak the nav item variable based on if group has forum or not
418 $this->enable_nav_item = (bool) $checked;
419 }
420
421 /**
422 * Allow group members to have advanced privileges in group forum topics.
423 *
424 * @since 2.3.0 bbPress (r4716)
425 *
426 * @param array $caps
427 * @param string $cap
428 * @param int $user_id
429 * @param array $args
430 * @return array
431 */
432 public function map_group_forum_meta_caps( $caps = array(), $cap = '', $user_id = 0, $args = array() ) {
433 // Group request state only describes the logged-in user
434 if ( bbp_get_current_user_id() !== (int) $user_id ) {
435 return (array) apply_filters( 'bbp_map_group_forum_topic_meta_caps', $caps, $cap, $user_id, $args );
436 }
437
438 // Never replace an earlier hard denial
439 if ( in_array( 'do_not_allow', $caps, true ) ) {
440 return (array) apply_filters( 'bbp_map_group_forum_topic_meta_caps', $caps, $cap, $user_id, $args );
441 }
442
443 // Explicit objects must belong to the current group
444 if ( ! empty( $args[0] ) ) {
445 $post_id = (int) $args[0];
446 $post_type = get_post_type( $post_id );
447
448 switch ( $post_type ) {
449 case bbp_get_forum_post_type() :
450 $forum_id = $post_id;
451 break;
452
453 case bbp_get_topic_post_type() :
454 $forum_id = bbp_get_topic_forum_id( $post_id );
455 break;
456
457 case bbp_get_reply_post_type() :
458 $forum_id = bbp_get_reply_forum_id( $post_id );
459 break;
460
461 default :
462 $forum_id = 0;
463 break;
464 }
465
466 if ( empty( $forum_id ) || ! in_array( $forum_id, bbp_get_group_forum_ids(), true ) ) {
467 return (array) apply_filters( 'bbp_map_group_forum_topic_meta_caps', $caps, $cap, $user_id, $args );
468 }
469 }
470
471 switch ( $cap ) {
472
473 // If user is a group mmember, allow them to create content.
474 case 'publish_replies' :
475 case 'publish_topics' :
476 if ( bbp_group_is_banned() ) {
477 $caps = array( 'do_not_allow' );
478 } elseif ( bbp_group_is_member() || bbp_group_is_mod() || bbp_group_is_admin() ) {
479 $caps = array( 'participate' );
480 }
481 break;
482
483 // If user is a group mod ar admin, map to participate cap.
484 case 'moderate' :
485 case 'edit_topic' :
486 case 'edit_reply' :
487 case 'view_trash' :
488 case 'edit_others_replies' :
489 case 'edit_others_topics' :
490 if ( bbp_group_is_mod() || bbp_group_is_admin() ) {
491 $caps = array( 'participate' );
492 }
493 break;
494
495 // If user is a group admin, allow them to delete topics and replies.
496 case 'delete_topic' :
497 case 'delete_reply' :
498 if ( bbp_group_is_admin() ) {
499 $caps = array( 'participate' );
500 }
501 break;
502
503 // If user is a group admin, allow them to manage forum attributes.
504 case 'manage_forum_attributes' :
505 $forum_id = ! empty( $args[0] ) ? bbp_get_forum_id( $args[0] ) : 0;
506 if ( bbp_is_forum( $forum_id ) && bbp_group_is_admin() && in_array( $forum_id, bbp_get_group_forum_ids(), true ) ) {
507 $caps = array( 'participate' );
508 }
509 break;
510 }
511
512 /**
513 * Filters the Group Forum Topic meta capabilities.
514 *
515 * @since 2.2.0 bbPress (r4435)
516 *
517 * @param array $caps Capabilities for the meta capability.
518 * @param string $cap Capability name.
519 * @param int $user_id User ID.
520 * @param array $args Arguments.
521 */
522 return (array) apply_filters( 'bbp_map_group_forum_topic_meta_caps', $caps, $cap, $user_id, $args );
523 }
524
525 /**
526 * Remove the topic meta cap map, so it doesn't interfere with sidebars.
527 *
528 * @since 2.3.0 bbPress (r4717)
529 */
530 public function remove_group_forum_meta_cap_map() {
531 remove_filter( 'bbp_map_meta_caps', array( $this, 'map_group_forum_meta_caps' ), 10 );
532 }
533
534 /**
535 * Validate the forum ID for a topic in a group forum.
536 *
537 * This method ensures that when a topic is saved, it is only allowed to be
538 * saved to a forum that is either:
539 *
540 * - A forum in the current group
541 * - A forum the current user can moderate outside of this group
542 *
543 * If all checks fail, an error gets added to prevent the topic from saving.
544 *
545 * @since 2.6.14 bbPress (r7060)
546 *
547 * @param int $topic_id Topic id.
548 */
549 public function validate_topic_forum_id( $topic_id = 0 ) {
550
551 // Bail if no topic
552 if ( empty( $topic_id ) ) {
553 return;
554 }
555
556 // Get current forum ID
557 $forum_id = bbp_get_topic_forum_id( $topic_id );
558
559 // Bail if not a group forum
560 if ( ! bbp_is_forum_group_forum( $forum_id ) ) {
561 return;
562 }
563
564 // Get current group ID
565 $group_id = bp_get_current_group_id();
566
567 // Bail if unknown group ID
568 if ( empty( $group_id ) ) {
569 return;
570 }
571
572 // Get group forum IDs
573 $forum_ids = bbp_get_group_forum_ids( $group_id );
574
575 // Get posted forum ID
576 $new_forum_id = ! empty( $_POST['bbp_forum_id'] )
577 ? absint( $_POST['bbp_forum_id'] )
578 : 0;
579
580 // Bail if new forum ID is a forum in this group
581 if ( in_array( $new_forum_id, $forum_ids, true ) ) {
582 return;
583 }
584
585 // Get the current user ID
586 $user_id = bbp_get_current_user_id();
587
588 // Bail if current user can moderate the new forum ID
589 if ( bbp_is_user_forum_moderator( $user_id, $new_forum_id ) ) {
590 return;
591 }
592
593 // If everything else has failed, then something is wrong and we need
594 // to add an error to prevent this topic from saving.
595 bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID is invalid.', 'bbpress' ) );
596 }
597
598 /**
599 * Validate the reply to for a reply in a group forum.
600 *
601 * This method ensures that when a reply to is saved, it is only allowed to
602 * be saved to the current topic.
603 *
604 * If all checks fail, an error gets added to prevent the reply from saving.
605 *
606 * @since 2.6.14 bbPress (r7060)
607 *
608 * @param int $reply_id Reply id.
609 */
610 public function validate_reply_to_id( $reply_id = 0 ) {
611
612 // Bail if no reply
613 if ( empty( $reply_id ) ) {
614 return;
615 }
616
617 // Get posted reply to
618 $new_reply_to = ! empty( $_POST['bbp_reply_to'] )
619 ? absint( $_POST['bbp_reply_to'] )
620 : 0;
621
622 // Bail if no reply to (assumes topic ID)
623 if ( empty( $new_reply_to ) ) {
624 return;
625 }
626
627 // Get current forum ID
628 $forum_id = bbp_get_reply_forum_id( $reply_id );
629
630 // Bail if not a group forum
631 if ( ! bbp_is_forum_group_forum( $forum_id ) ) {
632 return;
633 }
634
635 // Get current group ID
636 $group_id = bp_get_current_group_id();
637
638 // Bail if unknown group ID
639 if ( empty( $group_id ) ) {
640 return;
641 }
642
643 // Get current topic ID
644 $topic_id = bbp_get_reply_topic_id( $reply_id );
645
646 // Get topic reply IDs
647 $reply_ids = bbp_get_public_child_ids( $topic_id, bbp_get_reply_post_type() );
648
649 // Avoid recursion
650 unset( $reply_ids[ $reply_id ] );
651
652 // Bail if new reply parent ID is in this topic
653 if ( in_array( $new_reply_to, $reply_ids, true ) ) {
654 return;
655 }
656
657 // Add an error to prevent this reply from saving.
658 bbp_add_error( 'bbp_reply_to_id', __( '<strong>Error</strong>: Reply To is invalid.', 'bbpress' ) );
659 }
660
661 /** Edit ******************************************************************/
662
663 /**
664 * Show forums and new forum form when editing a group.
665 *
666 * @since 2.1.0 bbPress (r3552)
667 *
668 * @param object $group (the group to edit if in Group Admin UI)
669 */
670 public function edit_screen( $group = false ) {
671 $forum_id = 0;
672 $group_id = empty( $group->id ) ? bp_get_new_group_id() : $group->id;
673 $forum_ids = bbp_get_group_forum_ids( $group_id );
674
675 // Get the first forum ID
676 if ( ! empty( $forum_ids ) ) {
677 $forum_id = (int) is_array( $forum_ids ) ? $forum_ids[0] : $forum_ids;
678 }
679
680 // Should box be checked already?
681 $checked = is_admin() ? bp_group_is_forum_enabled( $group ) : bp_get_new_group_enable_forum() || bp_group_is_forum_enabled( bp_get_group_id() ); ?>
682
683 <h2><?php esc_html_e( 'Group Forum Settings', 'bbpress' ); ?></h2>
684
685 <fieldset>
686 <legend class="screen-reader-text"><?php esc_html_e( 'Group Forum Settings', 'bbpress' ); ?></legend>
687 <p><?php esc_html_e( 'Create a discussion forum to allow members of this group to communicate in a structured, bulletin-board style fashion.', 'bbpress' ); ?></p>
688
689 <div class="field-group">
690 <div class="checkbox">
691 <label for="bbp-edit-group-forum"><input type="checkbox" name="bbp-edit-group-forum" id="bbp-edit-group-forum" value="1"<?php checked( $checked ); ?> /> <?php esc_html_e( 'Yes. I want this group to have a forum.', 'bbpress' ); ?></label>
692 </div>
693
694 <p class="description"><?php esc_html_e( 'Saying no will not delete existing forum content.', 'bbpress' ); ?></p>
695 </div>
696
697 <?php if ( bbp_is_user_keymaster() ) : ?>
698 <div class="field-group">
699 <label for="bbp_group_forum_id"><?php esc_html_e( 'Group Forum:', 'bbpress' ); ?></label>
700 <?php
701 bbp_dropdown(
702 array(
703 'select_id' => 'bbp_group_forum_id',
704 'show_none' => esc_html__( '&mdash; No forum &mdash;', 'bbpress' ),
705 'selected' => $forum_id
706 )
707 );
708 ?>
709 <p class="description"><?php esc_html_e( 'Network administrators can reconfigure which forum belongs to this group.', 'bbpress' ); ?></p>
710 </div>
711 <?php endif; ?>
712
713 <?php if ( ! is_admin() ) : ?>
714 <input type="submit" value="<?php esc_attr_e( 'Save Settings', 'bbpress' ); ?>" />
715 <?php endif; ?>
716
717 </fieldset>
718
719 <?php
720
721 // Verify intent
722 if ( is_admin() ) {
723 wp_nonce_field( 'groups_edit_save_' . $this->slug, 'forum_group_admin_ui' );
724 } else {
725 wp_nonce_field( 'groups_edit_save_' . $this->slug );
726 }
727 }
728
729 /**
730 * Save the Group Forum data on edit.
731 *
732 * @since 2.1.0 bbPress (r3552)
733 *
734 * @param int $group_id (to handle Group Admin UI hook bp_group_admin_edit_after).
735 */
736 public function edit_screen_save( $group_id = 0 ) {
737
738 // Bail if not a POST action
739 if ( ! bbp_is_post_request() ) {
740 return;
741 }
742
743 // Admin Nonce check
744 if ( is_admin() ) {
745 check_admin_referer( 'groups_edit_save_' . $this->slug, 'forum_group_admin_ui' );
746
747 // Theme-side Nonce check
748 } elseif ( ! bbp_verify_nonce_request( 'groups_edit_save_' . $this->slug ) ) {
749 bbp_add_error( 'bbp_edit_group_forum_screen_save', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
750 return;
751 }
752
753 $edit_forum = ! empty( $_POST['bbp-edit-group-forum'] ) ? true : false;
754 $forum_id = 0;
755 $group_id = ! empty( $group_id ) ? $group_id : bp_get_current_group_id();
756
757 // Keymasters have the ability to reconfigure forums
758 if ( bbp_is_user_keymaster() ) {
759 $forum_ids = ! empty( $_POST['bbp_group_forum_id'] ) ? (array) (int) $_POST['bbp_group_forum_id'] : array();
760
761 // Use the existing forum IDs
762 } else {
763 $forum_ids = array_values( bbp_get_group_forum_ids( $group_id ) );
764 }
765
766 // Normalize group forum relationships now
767 if ( ! empty( $forum_ids ) ) {
768
769 // Loop through forums, and make sure they exist
770 foreach ( $forum_ids as $index => $forum_id ) {
771
772 // Look for forum
773 $forum = bbp_get_forum( $forum_id );
774
775 // No forum exists, so break the relationship
776 if ( empty( $forum ) ) {
777 $this->remove_forum(
778 array(
779 'forum_id' => $forum_id,
780 'group_id' => $group_id
781 )
782 );
783 unset( $forum_ids[ $index ] );
784 }
785 }
786
787 // No support for multiple forums yet
788 $forum_ids = array_values( $forum_ids );
789 $forum_id = ! empty( $forum_ids ) ? (int) $forum_ids[0] : 0;
790 }
791
792 // Update the group ID and forum ID relationships
793 bbp_update_group_forum_ids( $group_id, (array) $forum_ids );
794 if ( ! empty( $forum_id ) ) {
795 bbp_update_forum_group_ids( $forum_id, (array) $group_id );
796 }
797
798 // Update the group forum setting
799 $group = $this->toggle_group_forum( $group_id, $edit_forum );
800
801 // Create a new forum
802 if ( empty( $forum_id ) && ( true === $edit_forum ) ) {
803
804 // Set the default forum status
805 switch ( $group->status ) {
806 case 'hidden' :
807 $status = bbp_get_hidden_status_id();
808 break;
809 case 'private' :
810 $status = bbp_get_private_status_id();
811 break;
812 case 'public' :
813 default :
814 $status = bbp_get_public_status_id();
815 break;
816 }
817
818 // Create the initial forum
819 $forum_id = bbp_insert_forum(
820 array(
821 'post_parent' => bbp_get_group_forums_root_id(),
822 'post_title' => $group->name,
823 'post_content' => $group->description,
824 'post_status' => $status
825 )
826 );
827
828 // Setup forum args with forum ID
829 $new_forum_args = array( 'forum_id' => $forum_id );
830
831 // If in admin, also include the group ID
832 if ( is_admin() && ! empty( $group_id ) ) {
833 $new_forum_args['group_id'] = $group_id;
834 }
835
836 // Run the BP-specific functions for new groups
837 $this->new_forum( $new_forum_args );
838 }
839
840 // Redirect after save when not in admin
841 if ( ! is_admin() ) {
842 bp_core_redirect( trailingslashit( $this->group_url( buddypress()->groups->current_group ) . '/admin/' . $this->slug ) );
843 }
844 }
845
846 /**
847 * Adds a meta-box to BuddyPress Group Admin UI.
848 *
849 * @since 2.3.0 bbPress (r4815)
850 */
851 public function group_admin_ui_edit_screen() {
852 add_meta_box(
853 'bbpress_group_admin_ui_meta_box',
854 esc_html_x( 'Forum', 'group admin edit screen', 'bbpress' ),
855 array( $this, 'group_admin_ui_display_metabox' ),
856 get_current_screen()->id,
857 'side',
858 'core'
859 );
860 }
861
862 /**
863 * Displays the bbPress meta-box in BuddyPress Group Admin UI.
864 *
865 * @since 2.3.0 bbPress (r4815)
866 *
867 * @param object $item (group object).
868 */
869 public function group_admin_ui_display_metabox( $item ) {
870 $this->edit_screen( $item );
871 }
872
873 /** Create ****************************************************************/
874
875 /**
876 * Show forums and new forum form when creating a group.
877 *
878 * @since 2.1.0 bbPress (r3552)
879 */
880 public function create_screen( $group_id = 0 ) {
881
882 // Bail if not looking at this screen
883 if ( ! bp_is_group_creation_step( $this->slug ) ) {
884 return false;
885 }
886
887 // Check for possibly empty group_id
888 if ( empty( $group_id ) ) {
889 $group_id = bp_get_new_group_id();
890 }
891
892 $checked = bp_get_new_group_enable_forum() || groups_get_groupmeta( $group_id, 'forum_id' ); ?>
893
894 <h2><?php esc_html_e( 'Group Forum', 'bbpress' ); ?></h2>
895
896 <p><?php esc_html_e( 'Create a discussion forum to allow members of this group to communicate in a structured, bulletin-board style fashion.', 'bbpress' ); ?></p>
897
898 <div class="checkbox">
899 <label for="bbp-create-group-forum"><input type="checkbox" name="bbp-create-group-forum" id="bbp-create-group-forum" value="1"<?php checked( $checked ); ?> /> <?php esc_html_e( 'Yes. I want this group to have a forum.', 'bbpress' ); ?></label>
900 </div>
901
902 <?php
903 }
904
905 /**
906 * Save the Group Forum data on create.
907 *
908 * @since 2.1.0 bbPress (r3552)
909 */
910 public function create_screen_save( $group_id = 0 ) {
911
912 // Nonce check
913 if ( ! bbp_verify_nonce_request( 'groups_create_save_' . $this->slug ) ) {
914 bbp_add_error( 'bbp_create_group_forum_screen_save', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
915 return;
916 }
917
918 // Check for possibly empty group_id
919 if ( empty( $group_id ) ) {
920 $group_id = bp_get_new_group_id();
921 }
922
923 $create_forum = ! empty( $_POST['bbp-create-group-forum'] ) ? true : false;
924 $forum_id = 0;
925 $forum_ids = bbp_get_group_forum_ids( $group_id );
926
927 if ( ! empty( $forum_ids ) ) {
928 $forum_id = (int) is_array( $forum_ids ) ? $forum_ids[0] : $forum_ids;
929 }
930
931 // Create a forum, or not
932 switch ( $create_forum ) {
933 case true :
934
935 // Bail if initial content was already created
936 if ( ! empty( $forum_id ) ) {
937 return;
938 }
939
940 // Set the default forum status
941 switch ( bp_get_new_group_status() ) {
942 case 'hidden' :
943 $status = bbp_get_hidden_status_id();
944 break;
945 case 'private' :
946 $status = bbp_get_private_status_id();
947 break;
948 case 'public' :
949 default :
950 $status = bbp_get_public_status_id();
951 break;
952 }
953
954 // Create the initial forum
955 $forum_id = bbp_insert_forum(
956 array(
957 'post_parent' => bbp_get_group_forums_root_id(),
958 'post_title' => bp_get_new_group_name(),
959 'post_content' => bp_get_new_group_description(),
960 'post_status' => $status
961 )
962 );
963
964 // Run the BP-specific functions for new groups
965 $this->new_forum( array( 'forum_id' => $forum_id ) );
966
967 // Update forum active
968 groups_update_groupmeta( bp_get_new_group_id(), '_bbp_forum_enabled_' . $forum_id, true );
969
970 // Toggle forum on
971 $this->toggle_group_forum( bp_get_new_group_id(), true );
972
973 break;
974 case false :
975
976 // Forum was created but is now being undone
977 if ( ! empty( $forum_id ) ) {
978
979 // Delete the forum
980 wp_delete_post( $forum_id, true );
981
982 // Delete meta values
983 groups_delete_groupmeta( bp_get_new_group_id(), 'forum_id' );
984 groups_delete_groupmeta( bp_get_new_group_id(), '_bbp_forum_enabled_' . $forum_id );
985
986 // Toggle forum off
987 $this->toggle_group_forum( bp_get_new_group_id(), false );
988 }
989
990 break;
991 }
992 }
993
994 /**
995 * Used to start an output buffer.
996 *
997 * @since 2.1.0 bbPress (r3746)
998 */
999 public function ob_start() {
1000 ob_start();
1001 }
1002
1003 /**
1004 * Used to end an output buffer.
1005 *
1006 * @since 2.1.0 bbPress (r3746)
1007 */
1008 public function ob_end_clean() {
1009 ob_end_clean();
1010 }
1011
1012 /**
1013 * Creating a group forum or category (including root for group).
1014 *
1015 * @since 2.1.0 bbPress (r3654)
1016 *
1017 * @param array $forum_args
1018 *
1019 * @return void if no forum_id is available.
1020 */
1021 public function new_forum( $forum_args = array() ) {
1022
1023 // Bail if no forum_id was passed
1024 if ( empty( $forum_args['forum_id'] ) ) {
1025 return;
1026 }
1027
1028 // Validate forum_id
1029 $forum_id = bbp_get_forum_id( $forum_args['forum_id'] );
1030 $group_id = ! empty( $forum_args['group_id'] )
1031 ? $forum_args['group_id']
1032 : bp_get_current_group_id();
1033
1034 bbp_add_forum_id_to_group( $group_id, $forum_id );
1035 bbp_add_group_id_to_forum( $forum_id, $group_id );
1036 }
1037
1038 /**
1039 * Removing a group forum or category (including root for group).
1040 *
1041 * @since 2.1.0 bbPress (r3654)
1042 *
1043 * @param array $forum_args
1044 *
1045 * @return void if no forum_id is available.
1046 */
1047 public function remove_forum( $forum_args = array() ) {
1048
1049 // Bail if no forum_id was passed
1050 if ( empty( $forum_args['forum_id'] ) ) {
1051 return;
1052 }
1053
1054 // Validate forum_id
1055 $forum_id = bbp_get_forum_id( $forum_args['forum_id'] );
1056 $group_id = ! empty( $forum_args['group_id'] )
1057 ? $forum_args['group_id']
1058 : bp_get_current_group_id();
1059
1060 bbp_remove_forum_id_from_group( $group_id, $forum_id );
1061 bbp_remove_group_id_from_forum( $forum_id, $group_id );
1062
1063 // A private group forum must not become a regular private forum when
1064 // its last group relationship is removed.
1065 if ( empty( bbp_get_forum_group_ids( $forum_id ) ) && bbp_is_forum_private( $forum_id, false ) ) {
1066 bbp_hide_forum( $forum_id, bbp_get_private_status_id() );
1067 }
1068 }
1069
1070 /**
1071 * Listening to BuddyPress Group deletion to remove the forum.
1072 *
1073 * @since 2.3.0 bbPress (r4815)
1074 *
1075 * @param int $group_id The group ID.
1076 */
1077 public function disconnect_forum_from_group( $group_id = 0 ) {
1078
1079 // Bail if no group ID available
1080 if ( empty( $group_id ) ) {
1081 return;
1082 }
1083
1084 // Get the forums for the current group
1085 $forum_ids = bbp_get_group_forum_ids( $group_id );
1086
1087 // Bail if no forum IDs available
1088 if ( empty( $forum_ids ) ) {
1089 return;
1090 }
1091
1092 foreach ( (array) $forum_ids as $forum_id ) {
1093 $this->remove_forum(
1094 array(
1095 'forum_id' => (int) $forum_id,
1096 'group_id' => $group_id
1097 )
1098 );
1099 }
1100 }
1101
1102 /**
1103 * Update forum attributes to match those of the associated group.
1104 *
1105 * Fired whenever a group is saved.
1106 *
1107 * @since 2.6.7 bbPress (r7210)
1108 *
1109 * @param BP_Groups_Group $group Group object.
1110 */
1111 public static function update_group_forum( BP_Groups_Group $group ) {
1112
1113 // Get group forum IDs
1114 $forum_ids = bbp_get_group_forum_ids( $group->id );
1115
1116 // Bail if no forum IDs available
1117 if ( empty( $forum_ids ) ) {
1118 return;
1119 }
1120
1121 // Loop through forum IDs
1122 foreach ( $forum_ids as $forum_id ) {
1123
1124 // Get forum from ID
1125 $forum = bbp_get_forum( $forum_id );
1126
1127 // Check for change
1128 if ( $group->status !== $forum->post_status ) {
1129 switch ( $group->status ) {
1130
1131 // Changed to hidden
1132 case 'hidden' :
1133 bbp_hide_forum( $forum_id, $forum->post_status );
1134 break;
1135
1136 // Changed to private
1137 case 'private' :
1138 bbp_privatize_forum( $forum_id, $forum->post_status );
1139 break;
1140
1141 // Changed to public
1142 case 'public' :
1143 default :
1144 bbp_publicize_forum( $forum_id, $forum->post_status );
1145 break;
1146 }
1147 }
1148 }
1149
1150 // Maybe update the first group forum title, content, and slug
1151 if ( ! empty( $forum_ids[0] ) ) {
1152
1153 // Get forum from ID
1154 $forum = bbp_get_forum( $forum_ids[0] );
1155
1156 // Only update the forum if changes are being made
1157 if (
1158
1159 // Title
1160 ( $forum->post_title !== $group->name )
1161
1162 ||
1163
1164 // Content
1165 ( $forum->post_content !== $group->description )
1166
1167 ||
1168
1169 // Slug
1170 ( $forum->post_name !== $group->slug )
1171 ) {
1172 wp_update_post(
1173 array(
1174 'ID' => $forum->ID,
1175 'post_title' => $group->name,
1176 'post_content' => $group->description,
1177 'post_name' => $group->slug
1178 )
1179 );
1180 }
1181 }
1182 }
1183
1184 /**
1185 * Toggle the enable_forum group setting on or off.
1186 *
1187 * @since 2.3.0 bbPress (r4613)
1188 *
1189 * @param int $group_id The group to toggle.
1190 * @param bool $enabled True for on, false for off.
1191 * @return False if group is not found, otherwise return the group.
1192 */
1193 public function toggle_group_forum( $group_id = 0, $enabled = false ) {
1194
1195 // Get the group
1196 $group = groups_get_group( array( 'group_id' => $group_id ) );
1197
1198 // Bail if group cannot be found
1199 if ( empty( $group ) ) {
1200 return false;
1201 }
1202
1203 // Set forum enabled status
1204 $group->enable_forum = (int) $enabled;
1205
1206 // Save the group
1207 $group->save();
1208
1209 // Maybe disconnect forum from group
1210 if ( empty( $enabled ) ) {
1211 $this->disconnect_forum_from_group( $group_id );
1212 }
1213
1214 // Update internal private and forum ID variables
1215 bbp_repair_forum_visibility();
1216
1217 // Return the group
1218 return $group;
1219 }
1220
1221 /** Display Methods *******************************************************/
1222
1223 /**
1224 * Output the forums for a group in the edit screens.
1225 *
1226 * As of right now, bbPress only supports 1-to-1 group forum relationships.
1227 * In the future, many-to-many should be allowed.
1228 *
1229 * @since 2.1.0 bbPress (r3746)
1230 */
1231 public function display_forums( $offset = 0 ) {
1232
1233 // Allow actions immediately before group forum output
1234 do_action( 'bbp_before_group_forum_display' );
1235
1236 // Load up bbPress once
1237 $bbp = bbpress();
1238
1239 /** Query Resets ******************************************************/
1240
1241 // Forum data
1242 $forum_action = bp_action_variable( $offset );
1243 $forum_ids = bbp_get_group_forum_ids( bp_get_current_group_id() );
1244 $forum_id = array_shift( $forum_ids );
1245
1246 // Always load up the group forum
1247 bbp_has_forums(
1248 array(
1249 'p' => $forum_id,
1250 'post_parent' => null
1251 )
1252 );
1253
1254 // Set the global forum ID
1255 $bbp->current_forum_id = $forum_id;
1256
1257 // Assume forum query
1258 bbp_set_query_name( 'bbp_single_forum' ); ?>
1259
1260 <div id="bbpress-forums" class="bbpress-wrapper">
1261
1262 <?php switch ( $forum_action ) :
1263
1264 /** Single Forum **********************************************/
1265
1266 case false :
1267 case 'page' :
1268
1269 // Strip the super stickies from topic query
1270 add_filter( 'bbp_get_super_stickies', array( $this, 'no_super_stickies' ), 10, 1 );
1271
1272 // Unset the super sticky option on topic form
1273 add_filter( 'bbp_get_topic_types', array( $this, 'unset_super_sticky' ), 10, 1 );
1274
1275 // Query forums and show them if they exist
1276 if ( bbp_forums() ) :
1277
1278 // Setup the forum
1279 bbp_the_forum();
1280
1281 // Only wrap title in H2 if not empty
1282 $title = bbp_get_forum_title();
1283 if ( ! empty( $title ) ) {
1284 echo '<h2>' . $title . '</h2>';
1285 }
1286
1287 // Output forum
1288 bbp_get_template_part( 'content', 'single-forum' );
1289
1290 // No forums found
1291 else : ?>
1292
1293 <div id="message" class="info">
1294 <p><?php esc_html_e( 'This group does not currently have a forum.', 'bbpress' ); ?></p>
1295 </div>
1296
1297 <?php endif;
1298
1299 break;
1300
1301 /** Single Topic **********************************************/
1302
1303 case $this->topic_slug :
1304
1305 // hide the 'to front' admin links
1306 add_filter( 'bbp_get_topic_stick_link', array( $this, 'hide_super_sticky_admin_link' ), 10, 2 );
1307
1308 // Get the topic
1309 bbp_has_topics(
1310 array(
1311 'name' => bp_action_variable( $offset + 1 ),
1312 'posts_per_page' => 1,
1313 'show_stickies' => false
1314 )
1315 );
1316
1317 // If no topic, 404
1318 if ( ! bbp_topics() ) {
1319 bp_do_404( bbp_get_forum_permalink( $forum_id ) );
1320
1321 // Only wrap title in H2 if not empty
1322 $title = bbp_get_forum_title();
1323 if ( ! empty( $title ) ) {
1324 echo '<h2>' . $title . '</h2>';
1325 }
1326
1327 // No topics
1328 bbp_get_template_part( 'feedback', 'no-topics' );
1329 break;
1330 }
1331
1332 // Setup the topic
1333 bbp_the_topic();
1334
1335 // Only wrap title in H2 if not empty
1336 $title = bbp_get_topic_title();
1337 if ( ! empty( $title ) ) {
1338 echo '<h2>' . $title . '</h2>';
1339 }
1340
1341 // Topic edit
1342 if ( bp_action_variable( $offset + 2 ) === bbp_get_edit_slug() ) :
1343
1344 // Unset the super sticky link on edit topic template
1345 add_filter( 'bbp_get_topic_types', array( $this, 'unset_super_sticky' ), 10, 1 );
1346
1347 // Get the main query object
1348 $wp_query = bbp_get_wp_query();
1349
1350 // Set the edit switches
1351 $wp_query->bbp_is_edit = true;
1352 $wp_query->bbp_is_topic_edit = true;
1353
1354 // Setup the global forum ID
1355 $bbp->current_topic_id = get_the_ID();
1356
1357 // Merge
1358 if ( ! empty( $_GET['action'] ) && 'merge' === $_GET['action'] ) :
1359 bbp_set_query_name( 'bbp_topic_merge' );
1360 bbp_get_template_part( 'form', 'topic-merge' );
1361
1362 // Split
1363 elseif ( ! empty( $_GET['action'] ) && 'split' === $_GET['action'] ) :
1364 bbp_set_query_name( 'bbp_topic_split' );
1365 bbp_get_template_part( 'form', 'topic-split' );
1366
1367 // Edit
1368 else :
1369 bbp_set_query_name( 'bbp_topic_form' );
1370 bbp_get_template_part( 'form', 'topic' );
1371
1372 endif;
1373
1374 // Single Topic
1375 else :
1376 bbp_set_query_name( 'bbp_single_topic' );
1377 bbp_get_template_part( 'content', 'single-topic' );
1378 endif;
1379 break;
1380
1381 /** Single Reply **********************************************/
1382
1383 case $this->reply_slug :
1384
1385 // Get the reply
1386 bbp_has_replies(
1387 array(
1388 'name' => bp_action_variable( $offset + 1 ),
1389 'posts_per_page' => 1
1390 )
1391 );
1392
1393 // Check the reply and its topic before rendering either one.
1394 $reply_visible = bbp_replies();
1395 if ( $reply_visible ) {
1396 $reply_id = bbp_get_reply_id( $bbp->reply_query->post->ID );
1397 $topic_id = bbp_get_reply_topic_id( $reply_id );
1398 $reply_visible = ( bbp_is_reply_public( $reply_id ) || current_user_can( 'read_reply', $reply_id ) ) && ( bbp_is_topic_public( $topic_id ) || current_user_can( 'read_topic', $topic_id ) );
1399 }
1400
1401 // If no topic, 404
1402 if ( ! $reply_visible ) {
1403 bp_do_404( bbp_get_forum_permalink( $forum_id ) );
1404
1405 // Only wrap title in H2 if not empty
1406 $title = bbp_get_forum_title();
1407 if ( ! empty( $title ) ) {
1408 echo '<h2>' . $title . '</h2>';
1409 }
1410
1411 // No replies
1412 bbp_get_template_part( 'feedback', 'no-replies' );
1413 break;
1414 }
1415
1416 // Setup the reply
1417 bbp_the_reply();
1418
1419 // Only wrap title in H2 if not empty
1420 $title = bbp_get_reply_title();
1421 if ( ! empty( $title ) ) {
1422 echo '<h2>' . $title . '</h2>';
1423 }
1424
1425 if ( bp_action_variable( $offset + 2 ) === bbp_get_edit_slug() ) :
1426
1427 // Get the main query object
1428 $wp_query = bbp_get_wp_query();
1429
1430 // Set the edit switches
1431 $wp_query->bbp_is_edit = true;
1432 $wp_query->bbp_is_reply_edit = true;
1433
1434 // Setup the global reply ID
1435 $bbp->current_reply_id = get_the_ID();
1436
1437 // Move
1438 if ( ! empty( $_GET['action'] ) && ( 'move' === $_GET['action'] ) ) :
1439 bbp_set_query_name( 'bbp_reply_move' );
1440 bbp_get_template_part( 'form', 'reply-move' );
1441
1442 // Edit
1443 else :
1444 bbp_set_query_name( 'bbp_reply_form' );
1445 bbp_get_template_part( 'form', 'reply' );
1446 endif;
1447 endif;
1448 break;
1449 endswitch;
1450
1451 // Reset the query
1452 // phpcs:ignore WordPress.WP.DiscouragedFunctions.wp_reset_query_wp_reset_query
1453 wp_reset_query(); ?>
1454
1455 </div><!-- #bbpress-forums -->
1456
1457 <?php
1458
1459 // Allow actions immediately after group forum output
1460 do_action( 'bbp_after_group_forum_display' );
1461 }
1462
1463 /** Super sticky filters ***************************************************/
1464
1465 /**
1466 * Strip super stickies from the topic query.
1467 *
1468 * @since 2.3.0 bbPress (r4809)
1469 *
1470 * @access private
1471 * @param array $super the super sticky post ID's.
1472 * @return array (empty)
1473 */
1474 public function no_super_stickies( $super = array() ) {
1475 $super = array();
1476 return $super;
1477 }
1478
1479 /**
1480 * Unset the type super sticky from topic type.
1481 *
1482 * @since 2.3.0 bbPress (r4809)
1483 *
1484 * @access private
1485 * @param array $args
1486 * @return array $args without the to-front link.
1487 */
1488 public function unset_super_sticky( $args = array() ) {
1489 if ( isset( $args['super'] ) ) {
1490 unset( $args['super'] );
1491 }
1492 return $args;
1493 }
1494
1495 /**
1496 * Ugly preg_replace to hide the to front admin link.
1497 *
1498 * @since 2.3.0 bbPress (r4809)
1499 *
1500 * @access private
1501 * @param string $retval
1502 * @param array $args
1503 * @return string $retval without the to-front link.
1504 */
1505 public function hide_super_sticky_admin_link( $retval = '', $args = array() ) {
1506 if ( strpos( $retval, '(' ) ) {
1507 $retval = preg_replace( '/(\(.+?)+(\))/i', '', $retval );
1508 }
1509
1510 return $retval;
1511 }
1512
1513 /** Redirect Helpers ******************************************************/
1514
1515 /**
1516 * Redirect to the group forum screen.
1517 *
1518 * @since 2.1.0 bbPress (r3789)
1519 *
1520 * @param str $redirect_url
1521 * @param str $redirect_to
1522 */
1523 public function new_topic_redirect_to( $redirect_url = '', $redirect_to = '', $topic_id = 0 ) {
1524 if ( bp_is_group() ) {
1525 $topic = bbp_get_topic( $topic_id );
1526 $topic_hash = '#post-' . $topic_id;
1527 $redirect_url = trailingslashit( $this->group_url( groups_get_current_group() ) ) . trailingslashit( $this->slug ) . trailingslashit( $this->topic_slug ) . trailingslashit( $topic->post_name ) . $topic_hash;
1528 }
1529
1530 return $redirect_url;
1531 }
1532
1533 /**
1534 * Redirect to the group forum screen.
1535 *
1536 * @since 2.1.0 bbPress (r3799)
1537 */
1538 public function new_reply_redirect_to( $redirect_url = '', $redirect_to = '', $reply_id = 0 ) {
1539
1540 if ( bp_is_group() ) {
1541 $topic_id = bbp_get_reply_topic_id( $reply_id );
1542 $topic = bbp_get_topic( $topic_id );
1543 $reply_position = bbp_get_reply_position( $reply_id, $topic_id );
1544 $reply_page = ceil( (int) $reply_position / (int) bbp_get_replies_per_page() );
1545 $reply_hash = '#post-' . $reply_id;
1546 $topic_url = trailingslashit( $this->group_url( groups_get_current_group() ) ) . trailingslashit( $this->slug ) . trailingslashit( $this->topic_slug ) . trailingslashit( $topic->post_name );
1547
1548 // Don't include pagination if on first page
1549 if ( 1 >= $reply_page ) {
1550 $redirect_url = trailingslashit( $topic_url ) . $reply_hash;
1551
1552 // Include pagination
1553 } else {
1554 $redirect_url = trailingslashit( $topic_url ) . trailingslashit( bbp_get_paged_slug() ) . trailingslashit( $reply_page ) . $reply_hash;
1555 }
1556
1557 // Add topic view query arg back to end if it is set
1558 if ( bbp_get_view_all() ) {
1559 $redirect_url = bbp_add_view_all( $redirect_url );
1560 }
1561 }
1562
1563 return $redirect_url;
1564 }
1565
1566 /**
1567 * Redirect to the group admin forum edit screen.
1568 *
1569 * @since 2.1.0 bbPress (r3654)
1570 */
1571 public function edit_redirect_to( $redirect_url = '' ) {
1572
1573 // Get the current group, if there is one
1574 $group = groups_get_current_group();
1575
1576 // If this is a group of any kind, empty out the redirect URL
1577 if ( bp_is_group_admin_screen( $this->slug ) ) {
1578 $redirect_url = trailingslashit( bp_get_root_domain() . '/' . bp_get_groups_root_slug() . '/' . $group->slug . '/admin/' . $this->slug );
1579 }
1580
1581 return $redirect_url;
1582 }
1583
1584 /** Form Helpers **********************************************************/
1585
1586 /**
1587 * Make Forum Parent a hidden field instead of a selectable one.
1588 *
1589 * @since 2.1.0 bbPress (r3746)
1590 */
1591 public function forum_parent() {
1592 ?>
1593
1594 <input type="hidden" name="bbp_forum_parent_id" id="bbp_forum_parent_id" value="<?php bbp_group_forums_root_id(); ?>" />
1595
1596 <?php
1597 }
1598
1599 /**
1600 * Output a dropdown for picking which group forum this topic is for.
1601 *
1602 * @since 2.1.0 bbPress (r3746)
1603 */
1604 public function topic_parent() {
1605
1606 // Get the group ID
1607 $gid = bp_get_current_group_id();
1608
1609 // Get the forum IDs for this group
1610 $forum_ids = bbp_get_group_forum_ids( $gid );
1611
1612 // Attempt to get the current topic forum ID
1613 $topic_id = bbp_get_topic_id();
1614 $forum_id = bbp_get_topic_forum_id( $topic_id );
1615
1616 // Setup the query arguments - note that these may be overridden later
1617 // by various bbPress visibility and capability filters.
1618 $args = array(
1619 'post_type' => bbp_get_forum_post_type(),
1620 'post_status' => bbp_get_public_status_id(),
1621 'include' => $forum_ids,
1622 'numberposts' => -1,
1623 'orderby' => 'menu_order',
1624 'order' => 'ASC',
1625 );
1626
1627 // Get the forum objects for these forum IDs
1628 $forums = get_posts( $args );
1629
1630 // Setup the dropdown arguments
1631 $dd_args = array(
1632 'posts' => $forums,
1633 'selected' => $forum_id,
1634 ); ?>
1635
1636 <p>
1637 <label for="bbp_forum_id"><?php esc_html_e( 'Forum:', 'bbpress' ); ?></label><br />
1638 <?php bbp_dropdown( $dd_args ); ?>
1639 </p>
1640
1641 <?php
1642 }
1643
1644 /**
1645 * Permissions to view the 'New Topic'/'Reply To' form in a BuddyPress group.
1646 *
1647 * @since 2.3.0 bbPress (r4609)
1648 *
1649 * @param bool $retval Are we allowed to view the reply form?
1650 *
1651 * @return bool
1652 */
1653 public function form_permissions( $retval = false ) {
1654
1655 // Bail if user is not logged in
1656 if ( ! is_user_logged_in() ) {
1657 return $retval;
1658
1659 // Keymasters can always pass go
1660 } elseif ( bbp_is_user_keymaster() ) {
1661 $retval = true;
1662
1663 // Non-members cannot see forms
1664 } elseif ( ! bbp_group_is_member() ) {
1665 $retval = false;
1666
1667 // Banned users cannot see forms
1668 } elseif ( bbp_group_is_banned() ) {
1669 $retval = false;
1670 }
1671
1672 return $retval;
1673 }
1674
1675 /**
1676 * Add a hidden input field on the group settings page if the group forum is
1677 * enabled.
1678 *
1679 * Due to the way BuddyPress' group admin settings page saves its settings,
1680 * we need to let BP know that bbPress added a forum.
1681 *
1682 * @since 2.4.0 bbPress (r5027)
1683 *
1684 * @link https://bbpress.trac.wordpress.org/ticket/2339/
1685 * @see groups_screen_group_admin_settings()
1686 */
1687 public function group_settings_hidden_field() {
1688
1689 // if a forum is not enabled, we don't need to add this field
1690 if ( ! bp_group_is_forum_enabled() ) {
1691 return;
1692 } ?>
1693
1694 <input type="hidden" name="group-show-forum" id="group-show-forum" value="1" />
1695
1696 <?php
1697 }
1698
1699 /** Permalink Mappers *****************************************************/
1700
1701 /**
1702 * Get the URL for a group.
1703 *
1704 * @since 2.6.14 bbPress (r7316)
1705 *
1706 * @param int $group_id
1707 * @return string
1708 */
1709 private function group_url( $group_id = 0 ) {
1710
1711 // Default return value
1712 $retval = '';
1713
1714 // BuddyPress < 12.0 (deprecated code is intentionally included)
1715 if ( function_exists( 'bp_get_group_permalink' ) ) {
1716 $retval = bp_get_group_permalink( $group_id );
1717
1718 // BuddyPress > 12.0 (rewrite rules)
1719 } elseif ( function_exists( 'bp_get_group_url' ) ) {
1720 $retval = bp_get_group_url( $group_id );
1721 }
1722
1723 // Return
1724 return $retval;
1725 }
1726
1727 /**
1728 * Get the management URL for a group.
1729 *
1730 * @since 2.6.14 bbPress (r7316)
1731 *
1732 * @param int $group_id
1733 * @return string
1734 */
1735 private function group_manage_url( $group_id = 0 ) {
1736
1737 // Default return value
1738 $retval = '';
1739
1740 // BuddyPress < 12.0 (deprecated code is intentionally included)
1741 if ( function_exists( 'bp_get_group_admin_permalink' ) ) {
1742 $retval = bp_get_group_admin_permalink( $group_id );
1743
1744 // BuddyPress > 12.0 (rewrite rules)
1745 } elseif ( function_exists( 'bp_get_group_manage_url' ) ) {
1746 $retval = bp_get_group_manage_url( $group_id );
1747 }
1748
1749 // Return
1750 return $retval;
1751 }
1752
1753 /**
1754 * Maybe map a bbPress forum/topic/reply permalink to the corresponding group.
1755 *
1756 * @since 2.2.0 bbPress (r4395)
1757 *
1758 * @param int $post_id
1759 * @return Bail early if not a group forum post.
1760 * @return string
1761 */
1762 private function maybe_map_permalink_to_group( $post_id = 0, $url = false ) {
1763
1764 switch ( get_post_type( $post_id ) ) {
1765
1766 // Reply
1767 case bbp_get_reply_post_type() :
1768 $forum_id = bbp_get_reply_forum_id( $post_id );
1769 $url_end = trailingslashit( $this->reply_slug ) . get_post_field( 'post_name', $post_id );
1770 break;
1771
1772 // Topic
1773 case bbp_get_topic_post_type() :
1774 $forum_id = bbp_get_topic_forum_id( $post_id );
1775 $url_end = trailingslashit( $this->topic_slug ) . get_post_field( 'post_name', $post_id );
1776 break;
1777
1778 // Forum
1779 case bbp_get_forum_post_type() :
1780 $forum_id = $post_id;
1781 $url_end = ''; //get_post_field( 'post_name', $post_id );
1782 break;
1783
1784 // Unknown
1785 default :
1786 return $url;
1787 }
1788
1789 // Get group ID's for this forum
1790 $group_ids = bbp_get_forum_group_ids( $forum_id );
1791
1792 // Bail if the post isn't associated with a group
1793 if ( empty( $group_ids ) ) {
1794 return $url;
1795 }
1796
1797 // @todo Multiple group forums/forum groups
1798 $group_id = $group_ids[0];
1799 $group = groups_get_group( array( 'group_id' => $group_id ) );
1800
1801 // Admin
1802 $group_permalink = bp_is_group_admin_screen( $this->slug )
1803 ? $this->group_manage_url( $group )
1804 : $this->group_url( $group );
1805
1806 return trailingslashit( trailingslashit( trailingslashit( $group_permalink ) . $this->slug ) . $url_end );
1807 }
1808
1809 /**
1810 * Map a forum permalink to its corresponding group.
1811 *
1812 * @since 2.1.0 bbPress (r3746)
1813 *
1814 * @param string $url
1815 * @param int $forum_id
1816 * @return string
1817 */
1818 public function map_forum_permalink_to_group( $url, $forum_id ) {
1819 return $this->maybe_map_permalink_to_group( $forum_id, $url );
1820 }
1821
1822 /**
1823 * Map a topic permalink to its group forum.
1824 *
1825 * @since 2.1.0 bbPress (r3746)
1826 *
1827 * @param string $url
1828 * @param int $topic_id
1829 * @return string
1830 */
1831 public function map_topic_permalink_to_group( $url, $topic_id ) {
1832 return $this->maybe_map_permalink_to_group( $topic_id, $url );
1833 }
1834
1835 /**
1836 * Map a reply permalink to its group forum.
1837 *
1838 * @since 2.1.0 bbPress (r3746)
1839 *
1840 * @param string $url
1841 * @param int $reply_id
1842 * @return string
1843 */
1844 public function map_reply_permalink_to_group( $url, $reply_id ) {
1845 return $this->maybe_map_permalink_to_group( bbp_get_reply_topic_id( $reply_id ), $url );
1846 }
1847
1848 /**
1849 * Map a reply edit link to its group forum.
1850 *
1851 * @since 2.2.0 bbPress (r4395)
1852 *
1853 * @param string $url
1854 * @param int $reply_id
1855 * @return string
1856 */
1857 public function map_reply_edit_url_to_group( $url, $reply_id ) {
1858 $new = $this->maybe_map_permalink_to_group( $reply_id );
1859
1860 if ( empty( $new ) ) {
1861 return $url;
1862 }
1863
1864 return trailingslashit( $new ) . bbpress()->edit_id . '/';
1865 }
1866
1867 /**
1868 * Map a post link to its group forum.
1869 *
1870 * @since 2.2.0 bbPress (r4395)
1871 *
1872 * @param string $url
1873 * @param obj $post
1874 * @param boolean $leavename
1875 * @return string
1876 */
1877 public function post_link( $url, $post ) {
1878 return $this->maybe_map_permalink_to_group( $post->ID, $url );
1879 }
1880
1881 /**
1882 * Map a page link to its group forum.
1883 *
1884 * @since 2.2.0 bbPress (r4395)
1885 *
1886 * @param string $url
1887 * @param int $post_id
1888 * @param $sample
1889 * @return string
1890 */
1891 public function page_link( $url, $post_id ) {
1892 return $this->maybe_map_permalink_to_group( $post_id, $url );
1893 }
1894
1895 /**
1896 * Map a custom post type link to its group forum.
1897 *
1898 * @since 2.2.0 bbPress (r4395)
1899 *
1900 * @param string $url
1901 * @param obj $post
1902 * @param $leavename
1903 * @param $sample
1904 * @return string
1905 */
1906 public function post_type_link( $url, $post ) {
1907 return $this->maybe_map_permalink_to_group( $post->ID, $url );
1908 }
1909
1910 /**
1911 * Fix pagination of topics on forum view.
1912 *
1913 * @since 2.2.0 bbPress (r4395)
1914 *
1915 * @param array $args
1916 * @return array
1917 */
1918 public function topic_pagination( $args ) {
1919 $new = $this->maybe_map_permalink_to_group( bbp_get_forum_id() );
1920
1921 if ( empty( $new ) ) {
1922 return $args;
1923 }
1924
1925 $args['base'] = trailingslashit( $new ) . bbp_get_paged_slug() . '/%#%/';
1926
1927 return $args;
1928 }
1929
1930 /**
1931 * Fix pagination of replies on topic view.
1932 *
1933 * @since 2.2.0 bbPress (r4395)
1934 *
1935 * @param array $args
1936 * @return array
1937 */
1938 public function replies_pagination( $args ) {
1939 $new = $this->maybe_map_permalink_to_group( bbp_get_topic_id() );
1940 if ( empty( $new ) ) {
1941 return $args;
1942 }
1943
1944 $args['base'] = trailingslashit( $new ) . bbp_get_paged_slug() . '/%#%/';
1945
1946 return $args;
1947 }
1948
1949 /**
1950 * Fixes rewrite pagination in BuddyPress Group Forums & Topics.
1951 *
1952 * Required for compatibility with BuddyPress > 12.0, where the /groups/
1953 * rewrite rule will be caught before bbPress's /page/ rule.
1954 *
1955 * @since 2.6.14 bbPress (r7316)
1956 *
1957 * @param object $query Verified query object.
1958 * @param string $type Type of variable to compare to.
1959 * @return mixed Verified object if valid, Default or null if invalid.
1960 */
1961 public function rewrite_pagination( $query, $type = '' ) {
1962
1963 // Bail if wrong global
1964 if ( 'wp_query' !== $type ) {
1965 return $query;
1966 }
1967
1968 // Bail if not inside a BuddyPress Group
1969 if ( ! bp_is_group() ) {
1970 return $query;
1971 }
1972
1973 // Bail if not inside a BuddyPress Group Forum
1974 if ( ! bp_is_current_action( 'forum' ) ) {
1975 return $query;
1976 }
1977
1978 // Default "paged" value
1979 $page_number = null;
1980
1981 // Can't use bbp_is_single_topic() because it triggers a loop.
1982 $is_single_topic = bp_is_action_variable( 'topic', 0 );
1983
1984 // Single Topic
1985 if ( true === $is_single_topic ) {
1986
1987 // Get the page number from 3rd position
1988 if ( bp_is_action_variable( 'page', 2 ) ) {
1989 $page_number = bp_action_variable( 3 );
1990 }
1991
1992 // Default (Single Forum)
1993 } elseif ( bp_is_action_variable( 'page', 0 ) ) {
1994 $page_number = bp_action_variable( 1 );
1995 }
1996
1997 // Bail if no page number
1998 if ( empty( $page_number ) ) {
1999 return $query;
2000 }
2001
2002 // Set the 'paged' WP_Query var to the new action-based value
2003 $query->set( 'paged', $page_number );
2004
2005 // Return the filtered/modified object
2006 return $query;
2007 }
2008
2009 /**
2010 * Ensure that forum content associated with a BuddyPress group can only be
2011 * viewed via the group URL.
2012 *
2013 * @since 2.2.0 bbPress (r4395)
2014 */
2015 public function redirect_canonical() {
2016
2017 // Bail if on a RSS feed
2018 if ( is_feed() ) {
2019 return;
2020 }
2021
2022 // Viewing a single forum
2023 if ( bbp_is_single_forum() ) {
2024 $forum_id = get_the_ID();
2025 $group_ids = bbp_get_forum_group_ids( $forum_id );
2026
2027 // Viewing a single topic
2028 } elseif ( bbp_is_single_topic() ) {
2029 $topic_id = get_the_ID();
2030 $slug = get_post_field( 'post_name', $topic_id );
2031 $forum_id = bbp_get_topic_forum_id( $topic_id );
2032 $group_ids = bbp_get_forum_group_ids( $forum_id );
2033
2034 // Not a forum or topic
2035 } else {
2036 return;
2037 }
2038
2039 // Bail if not a group forum
2040 if ( empty( $group_ids ) ) {
2041 return;
2042 }
2043
2044 // Use the first group ID
2045 $group_id = $group_ids[0];
2046 $group = groups_get_group( array( 'group_id' => $group_id ) );
2047 $group_link = trailingslashit( $this->group_url( $group ) );
2048 $redirect_to = trailingslashit( $group_link . $this->slug );
2049
2050 // Add topic slug to URL
2051 if ( bbp_is_single_topic() ) {
2052 $redirect_to = trailingslashit( $redirect_to . $this->topic_slug . '/' . $slug );
2053 }
2054
2055 bp_core_redirect( $redirect_to );
2056 }
2057
2058 /** Activity **************************************************************/
2059
2060 /**
2061 * Map a forum post to its corresponding group in the group activity stream.
2062 *
2063 * @since 2.2.0 bbPress (r4399)
2064 *
2065 * @param array $args Arguments from BBP_BuddyPress_Activity::record_activity()
2066 *
2067 * @return array
2068 */
2069 public function map_activity_to_group( $args = array() ) {
2070
2071 // Get current BP group
2072 $group = groups_get_current_group();
2073
2074 // Not posting from a BuddyPress group? stop now!
2075 if ( empty( $group ) ) {
2076 return $args;
2077 }
2078
2079 // Set the component to 'groups' so the activity item shows up in the group
2080 $args['component'] = buddypress()->groups->id;
2081
2082 // Move the forum post ID to the secondary item ID
2083 $args['secondary_item_id'] = $args['item_id'];
2084
2085 // Set the item ID to the group ID so the activity item shows up in the group
2086 $args['item_id'] = $group->id;
2087
2088 // Update the group's last activity
2089 groups_update_last_activity( $group->id );
2090
2091 return $args;
2092 }
2093 }
2094 endif;
2095