PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.4.0
Forumax – AI Powered Advanced Community Forum Plugin v2.4.0
2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 trunk 1.0.8 1.1.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 2.0.0 2.1.0 All 29 releases
bbp-core / lib / bbpress / includes / topics / template.php

template.php in Forumax – AI Powered Advanced Community Forum Plugin 2.4.0, at lib/bbpress/includes/topics/template.php

4,026 lines 115.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * bbPress Topic Template Tags
5 *
6 * @package bbPress
7 * @subpackage TemplateTags
8 */
9
10 // Exit if accessed directly
11 defined( 'ABSPATH' ) || exit;
12
13 /** Post Type *****************************************************************/
14
15 /**
16 * Output the unique id of the custom post type for topics
17 *
18 * @since 2.0.0 bbPress (r2857)
19 */
20 function bbp_topic_post_type() {
21 echo bbp_get_topic_post_type();
22 }
23 /**
24 * Return the unique id of the custom post type for topics
25 *
26 * @since 2.0.0 bbPress (r2857)
27 *
28 * @return string The unique topic post type id
29 */
30 function bbp_get_topic_post_type() {
31
32 // Filter & return
33 return apply_filters( 'bbp_get_topic_post_type', bbpress()->topic_post_type );
34 }
35
36 /**
37 * Return array of labels used by the topic post type
38 *
39 * @since 2.5.0 bbPress (r5129)
40 *
41 * @return array
42 */
43 function bbp_get_topic_post_type_labels() {
44
45 // Filter & return
46 return (array) apply_filters( 'bbp_get_topic_post_type_labels', array(
47 'name' => esc_attr__( 'Topics', 'bbpress' ),
48 'menu_name' => esc_attr__( 'Topics', 'bbpress' ),
49 'singular_name' => esc_attr__( 'Topic', 'bbpress' ),
50 'all_items' => esc_attr__( 'All Topics', 'bbpress' ),
51 'add_new' => esc_attr__( 'Add New', 'bbpress' ),
52 'add_new_item' => esc_attr__( 'Create New Topic', 'bbpress' ),
53 'edit' => esc_attr__( 'Edit', 'bbpress' ),
54 'edit_item' => esc_attr__( 'Edit Topic', 'bbpress' ),
55 'new_item' => esc_attr__( 'New Topic', 'bbpress' ),
56 'view' => esc_attr__( 'View Topic', 'bbpress' ),
57 'view_item' => esc_attr__( 'View Topic', 'bbpress' ),
58 'view_items' => esc_attr__( 'View Topics', 'bbpress' ),
59 'search_items' => esc_attr__( 'Search Topics', 'bbpress' ),
60 'not_found' => esc_attr__( 'No topics found', 'bbpress' ),
61 'not_found_in_trash' => esc_attr__( 'No topics found in Trash', 'bbpress' ),
62 'filter_items_list' => esc_attr__( 'Filter topics list', 'bbpress' ),
63 'items_list' => esc_attr__( 'Topics list', 'bbpress' ),
64 'items_list_navigation' => esc_attr__( 'Topics list navigation', 'bbpress' ),
65 'parent_item_colon' => esc_attr__( 'Forum:', 'bbpress' ),
66 'archives' => esc_attr__( 'Forum Topics', 'bbpress' ),
67 'attributes' => esc_attr__( 'Topic Attributes', 'bbpress' ),
68 'insert_into_item' => esc_attr__( 'Insert into topic', 'bbpress' ),
69 'uploaded_to_this_item' => esc_attr__( 'Uploaded to this topic', 'bbpress' ),
70 'featured_image' => esc_attr__( 'Topic Image', 'bbpress' ),
71 'set_featured_image' => esc_attr__( 'Set topic image', 'bbpress' ),
72 'remove_featured_image' => esc_attr__( 'Remove topic image', 'bbpress' ),
73 'use_featured_image' => esc_attr__( 'Use as topic image', 'bbpress' ),
74 'item_published' => esc_attr__( 'Topic published.', 'bbpress' ),
75 'item_published_privately' => esc_attr__( 'Topic published privately.', 'bbpress' ),
76 'item_reverted_to_draft' => esc_attr__( 'Topic reverted to draft.', 'bbpress' ),
77 'item_scheduled' => esc_attr__( 'Topic scheduled.', 'bbpress' ),
78 'item_updated' => esc_attr__( 'Topic updated.', 'bbpress' )
79 ) );
80 }
81
82 /**
83 * Return array of topic post type rewrite settings
84 *
85 * @since 2.5.0 bbPress (r5129)
86 *
87 * @return array
88 */
89 function bbp_get_topic_post_type_rewrite() {
90
91 // Filter & return
92 return (array) apply_filters( 'bbp_get_topic_post_type_rewrite', array(
93 'slug' => bbp_get_topic_slug(),
94 'with_front' => false
95 ) );
96 }
97
98 /**
99 * Return array of features the topic post type supports
100 *
101 * @since 2.5.0 bbPress (r5129)
102 *
103 * @return array
104 */
105 function bbp_get_topic_post_type_supports() {
106
107 // Filter & return
108 return (array) apply_filters( 'bbp_get_topic_post_type_supports', array(
109 'title',
110 'editor',
111 'revisions',
112 'thumbnail'
113 ) );
114 }
115
116 /**
117 * The plugin version of bbPress comes with two topic display options:
118 * - Traditional: Topics are included in the reply loop (default)
119 * - New Style: Topics appear as "lead" posts, ahead of replies
120 *
121 * @since 2.0.0 bbPress (r2954)
122 *
123 * @param $show_lead Optional. Default false
124 * @return bool Yes if the topic appears as a lead, otherwise false
125 */
126 function bbp_show_lead_topic( $show_lead = false ) {
127
128 // Never separate the lead topic in feeds
129 if ( is_feed() ) {
130 return false;
131 }
132
133 // Filter & return
134 return (bool) apply_filters( 'bbp_show_lead_topic', (bool) $show_lead );
135 }
136
137 /** Topic Loop ****************************************************************/
138
139 /**
140 * The main topic loop. WordPress makes this easy for us
141 *
142 * @since 2.0.0 bbPress (r2485)
143 *
144 * @param array $args All the arguments supported by {@link WP_Query}
145 * @return object Multidimensional array of topic information
146 */
147 function bbp_has_topics( $args = array() ) {
148
149 /** Defaults **************************************************************/
150
151 // Other defaults
152 $default_topic_search = bbp_sanitize_search_request( 'ts' );
153 $default_show_stickies = (bool) ( bbp_is_single_forum() || bbp_is_topic_archive() ) && ( false === $default_topic_search );
154 $default_post_parent = bbp_is_single_forum() ? bbp_get_forum_id() : 'any';
155
156 // Default argument array
157 $default = array(
158 'post_type' => bbp_get_topic_post_type(), // Narrow query down to bbPress topics
159 'post_parent' => $default_post_parent, // Forum ID
160 'meta_key' => '_bbp_last_active_time', // Make sure topic has some last activity time
161 'meta_type' => 'DATETIME',
162 'orderby' => 'meta_value', // 'meta_value', 'author', 'date', 'title', 'modified', 'parent', rand',
163 'order' => 'DESC', // 'ASC', 'DESC'
164 'posts_per_page' => bbp_get_topics_per_page(), // Topics per page
165 'paged' => bbp_get_paged(), // Page Number
166 'show_stickies' => $default_show_stickies, // Ignore sticky topics?
167 'max_num_pages' => false, // Maximum number of pages to show
168
169 // Conditionally prime the cache for related posts
170 'update_post_family_cache' => true
171 );
172
173 // Only add 's' arg if searching for topics
174 // See https://bbpress.trac.wordpress.org/ticket/2607
175 if ( ! empty( $default_topic_search ) ) {
176 $default['s'] = $default_topic_search;
177 }
178
179 // What are the default allowed statuses (based on user caps)
180 if ( bbp_get_view_all( 'edit_others_topics' ) ) {
181
182 // Default view=all statuses
183 $post_statuses = array_keys( bbp_get_topic_statuses() );
184
185 // Add support for private status
186 if ( current_user_can( 'read_private_topics' ) ) {
187 $post_statuses[] = bbp_get_private_status_id();
188 }
189
190 // Join post statuses together
191 $default['post_status'] = $post_statuses;
192
193 // Lean on the 'perm' query var value of 'readable' to provide statuses
194 } else {
195 $default['perm'] = 'readable';
196 }
197
198 // Maybe query for topic tags
199 if ( bbp_is_topic_tag() ) {
200 $default['term'] = bbp_get_topic_tag_slug();
201 $default['taxonomy'] = bbp_get_topic_tag_tax_id();
202 }
203
204 /** Setup *****************************************************************/
205
206 // Parse arguments against default values
207 $r = bbp_parse_args( $args, $default, 'has_topics' );
208
209 // Get bbPress
210 $bbp = bbpress();
211
212 // Call the query
213 $bbp->topic_query = new WP_Query( $r );
214
215 // Maybe prime last active posts
216 if ( ! empty( $r['update_post_family_cache'] ) ) {
217 bbp_update_post_family_caches( $bbp->topic_query->posts );
218 }
219
220 // Set post_parent back to 0 if originally set to 'any'
221 if ( 'any' === $r['post_parent'] ) {
222 $r['post_parent'] = 0;
223 }
224
225 // Limited the number of pages shown
226 if ( ! empty( $r['max_num_pages'] ) ) {
227 $bbp->topic_query->max_num_pages = (int) $r['max_num_pages'];
228 }
229
230 /** Stickies **************************************************************/
231
232 // Put sticky posts at the top of the posts array
233 if ( ! empty( $r['show_stickies'] ) && ( $r['paged'] <= 1 ) ) {
234 bbp_add_sticky_topics( $bbp->topic_query, $r );
235 }
236
237 // If no limit to posts per page, set it to the current post_count
238 if ( -1 === $r['posts_per_page'] ) {
239 $r['posts_per_page'] = $bbp->topic_query->post_count;
240 }
241
242 // Add pagination values to query object
243 $bbp->topic_query->posts_per_page = (int) $r['posts_per_page'];
244 $bbp->topic_query->paged = (int) $r['paged'];
245
246 // Only add pagination if query returned results
247 if ( ( ! empty( $bbp->topic_query->post_count ) || ! empty( $bbp->topic_query->found_posts ) ) && ! empty( $bbp->topic_query->posts_per_page ) ) {
248
249 // Limit the number of topics shown based on maximum allowed pages
250 if ( ( ! empty( $r['max_num_pages'] ) ) && ( $bbp->topic_query->found_posts > ( $bbp->topic_query->max_num_pages * $bbp->topic_query->post_count ) ) ) {
251 $bbp->topic_query->found_posts = $bbp->topic_query->max_num_pages * $bbp->topic_query->post_count;
252 }
253
254 // Total topics for pagination boundaries
255 $total_pages = ( $bbp->topic_query->posts_per_page === $bbp->topic_query->found_posts )
256 ? 1
257 : ceil( $bbp->topic_query->found_posts / $bbp->topic_query->posts_per_page );
258
259 // Maybe add view-all args
260 $add_args = bbp_get_view_all()
261 ? array( 'view' => 'all' )
262 : false;
263
264 // Pagination settings with filter
265 $bbp_topic_pagination = apply_filters( 'bbp_topic_pagination', array(
266 'base' => bbp_get_topics_pagination_base( $r['post_parent'] ),
267 'format' => '',
268 'total' => $total_pages,
269 'current' => $bbp->topic_query->paged,
270 'prev_text' => is_rtl() ? '&rarr;' : '&larr;',
271 'next_text' => is_rtl() ? '&larr;' : '&rarr;',
272 'mid_size' => 1,
273 'add_args' => $add_args,
274 ) );
275
276 // Add pagination to query object
277 $bbp->topic_query->pagination_links = bbp_paginate_links( $bbp_topic_pagination );
278 }
279
280 // Filter & return
281 return apply_filters( 'bbp_has_topics', $bbp->topic_query->have_posts(), $bbp->topic_query );
282 }
283
284 /**
285 * Whether there are more topics available in the loop
286 *
287 * @since 2.0.0 bbPress (r2485)
288 *
289 * @return object Topic information
290 */
291 function bbp_topics() {
292
293 // Put into variable to check against next
294 $have_posts = bbpress()->topic_query->have_posts();
295
296 // Reset the post data when finished
297 if ( empty( $have_posts ) ) {
298 wp_reset_postdata();
299 }
300
301 return $have_posts;
302 }
303
304 /**
305 * Loads up the current topic in the loop
306 *
307 * @since 2.0.0 bbPress (r2485)
308 *
309 * @return object Topic information
310 */
311 function bbp_the_topic() {
312 return bbpress()->topic_query->the_post();
313 }
314
315 /**
316 * Add sticky topics to a topics query object
317 *
318 * @since 2.6.0 bbPress (r6402)
319 *
320 * @param WP_Query $query
321 * @param array $args
322 */
323 function bbp_add_sticky_topics( &$query, $args = array() ) {
324
325 // Bail if intercepted
326 $intercept = bbp_maybe_intercept( __FUNCTION__, func_get_args() );
327 if ( bbp_is_intercepted( $intercept ) ) {
328 return $intercept;
329 }
330
331 // Parse arguments against what gets used locally
332 $r = bbp_parse_args( $args, array(
333 'post_parent' => 0,
334 'post_parent__not_in' => array(),
335 'post__not_in' => array(),
336 'post_status' => '',
337 'perm' => ''
338 ), 'add_sticky_topics' );
339
340 // Get super stickies and stickies in this forum
341 $super_stickies = bbp_get_super_stickies();
342 $forum_stickies = ! empty( $r['post_parent'] )
343 ? bbp_get_stickies( $r['post_parent'] )
344 : array();
345
346 // Merge stickies (supers first) and remove duplicates
347 $stickies = array_filter( array_unique( array_merge( $super_stickies, $forum_stickies ) ) );
348
349 // Bail if no stickies
350 if ( empty( $stickies ) ) {
351 return;
352 }
353
354 // If any posts have been excluded specifically, Ignore those that are sticky.
355 if ( ! empty( $r['post__not_in'] ) ) {
356 $stickies = array_diff( $stickies, $r['post__not_in'] );
357 }
358
359 // Default sticky posts array
360 $sticky_topics = array();
361
362 // Loop through posts
363 foreach ( $query->posts as $key => $post ) {
364
365 // Looking for stickies in this query loop, and stash & unset them
366 if ( in_array( $post->ID, $stickies, true ) ) {
367 $sticky_topics[] = $post;
368 unset( $query->posts[ $key ] );
369 }
370 }
371
372 // Remove queried stickies from stickies array
373 if ( ! empty( $sticky_topics ) ) {
374 $stickies = array_diff( $stickies, wp_list_pluck( $sticky_topics, 'ID' ) );
375 }
376
377 // Fetch all stickies that were not in the query
378 if ( ! empty( $stickies ) ) {
379
380 // Query to use in get_posts to get sticky posts
381 $sticky_query = array(
382 'post_type' => bbp_get_topic_post_type(),
383 'post_parent' => 'any',
384 'meta_key' => '_bbp_last_active_time',
385 'meta_type' => 'DATETIME',
386 'orderby' => 'meta_value',
387 'order' => 'DESC',
388 'include' => $stickies
389 );
390
391 // Conditionally exclude private/hidden forum ID's
392 $exclude_forum_ids = bbp_exclude_forum_ids( 'array' );
393
394 // Maybe remove the current forum from excluded forum IDs
395 if ( ! empty( $r['post_parent' ] ) ) {
396 unset( $exclude_forum_ids[ $r['post_parent' ] ] );
397 }
398
399 // Maybe exclude specific forums
400 if ( ! empty( $exclude_forum_ids ) ) {
401 $sticky_query['post_parent__not_in'] = $exclude_forum_ids;
402 }
403
404 // Allowed statuses, or lean on the 'perm' argument (probably 'readable')
405 $sticky_query['post_status'] = bbp_get_view_all( 'edit_others_topics' )
406 ? $r['post_status']
407 : $r['perm'];
408
409 // Get unqueried stickies
410 $_posts = get_posts( $sticky_query );
411 if ( ! empty( $_posts ) ) {
412
413 // Merge the stickies topics with the query topics .
414 $sticky_topics = array_merge( $sticky_topics, $_posts );
415
416 // Get a count of the visible stickies
417 $sticky_count = count( $_posts );
418
419 // Adjust loop and counts for new sticky positions
420 $query->found_posts = (int) $query->found_posts + (int) $sticky_count;
421 $query->post_count = (int) $query->post_count + (int) $sticky_count;
422 }
423 }
424
425 // Bail if no sticky topics empty or not an array
426 if ( empty( $sticky_topics ) || ! is_array( $sticky_topics ) ) {
427 return;
428 }
429
430 // Default ordered stickies array
431 $ordered_stickies = array(
432 'supers' => array(),
433 'forums' => array()
434 );
435
436 // Separate supers from forums
437 foreach ( $sticky_topics as $post ) {
438 if ( in_array( $post->ID, $super_stickies, true ) ) {
439 $ordered_stickies['supers'][] = $post;
440 } elseif ( in_array( $post->ID, $forum_stickies, true ) ) {
441 $ordered_stickies['forums'][] = $post;
442 }
443 }
444
445 // Merge supers and forums, supers first
446 $sticky_topics = array_merge( $ordered_stickies['supers'], $ordered_stickies['forums'] );
447
448 // Update queried posts
449 $query->posts = array_merge( $sticky_topics, array_values( $query->posts ) );
450 }
451
452 /**
453 * Output the topic id
454 *
455 * @since 2.0.0 bbPress (r2485)
456 */
457 function bbp_topic_id( $topic_id = 0) {
458 echo bbp_get_topic_id( $topic_id );
459 }
460 /**
461 * Return the topic id
462 *
463 * @since 2.0.0 bbPress (r2485)
464 *
465 * @param $topic_id Optional. Used to check emptiness
466 * @return int The topic id
467 */
468 function bbp_get_topic_id( $topic_id = 0 ) {
469 $bbp = bbpress();
470 $wp_query = bbp_get_wp_query();
471
472 // Easy empty checking
473 if ( ! empty( $topic_id ) && is_numeric( $topic_id ) ) {
474 $bbp_topic_id = $topic_id;
475
476 // Currently inside a topic loop
477 } elseif ( ! empty( $bbp->topic_query->in_the_loop ) && isset( $bbp->topic_query->post->ID ) ) {
478 $bbp_topic_id = $bbp->topic_query->post->ID;
479
480 // Currently inside a search loop
481 } elseif ( ! empty( $bbp->search_query->in_the_loop ) && isset( $bbp->search_query->post->ID ) && bbp_is_topic( $bbp->search_query->post->ID ) ) {
482 $bbp_topic_id = $bbp->search_query->post->ID;
483
484 // Currently viewing/editing a topic, likely alone
485 } elseif ( ( bbp_is_single_topic() || bbp_is_topic_edit() ) && ! empty( $bbp->current_topic_id ) ) {
486 $bbp_topic_id = $bbp->current_topic_id;
487
488 // Currently viewing/editing a topic, likely in a loop
489 } elseif ( ( bbp_is_single_topic() || bbp_is_topic_edit() ) && isset( $wp_query->post->ID ) ) {
490 $bbp_topic_id = $wp_query->post->ID;
491
492 // Currently viewing/editing a reply
493 } elseif ( bbp_is_single_reply() || bbp_is_reply_edit() ) {
494 $bbp_topic_id = bbp_get_reply_topic_id();
495
496 // Fallback
497 } else {
498 $bbp_topic_id = 0;
499 }
500
501 // Filter & return
502 return (int) apply_filters( 'bbp_get_topic_id', (int) $bbp_topic_id, $topic_id );
503 }
504
505 /**
506 * Gets a topic
507 *
508 * @since 2.0.0 bbPress (r2787)
509 *
510 * @return mixed Null if error or topic (in specified form) if success
511 */
512 function bbp_get_topic( $topic, $output = OBJECT, $filter = 'raw' ) {
513
514 // Maybe get ID from empty or int
515 if ( empty( $topic ) || is_numeric( $topic ) ) {
516 $topic = bbp_get_topic_id( $topic );
517 }
518
519 // Bail if no post object
520 $topic = get_post( $topic, OBJECT, $filter );
521 if ( empty( $topic ) ) {
522 return $topic;
523 }
524
525 // Bail if not correct post type
526 if ( $topic->post_type !== bbp_get_topic_post_type() ) {
527 return null;
528 }
529
530 // Default return value is OBJECT
531 $retval = $topic;
532
533 // Array A
534 if ( $output === ARRAY_A ) {
535 $retval = get_object_vars( $topic );
536
537 // Array N
538 } elseif ( $output === ARRAY_N ) {
539 $retval = array_values( get_object_vars( $topic ) );
540 }
541
542 // Filter & return
543 return apply_filters( 'bbp_get_topic', $retval, $topic, $output, $filter );
544 }
545
546 /**
547 * Output the link to the topic in the topic loop
548 *
549 * @since 2.0.0 bbPress (r2485)
550 *
551 * @param int $topic_id Optional. Topic id
552 * @param string $redirect_to Optional. Pass a redirect value for use with
553 * shortcodes and other fun things.
554 */
555 function bbp_topic_permalink( $topic_id = 0, $redirect_to = '' ) {
556 echo esc_url( bbp_get_topic_permalink( $topic_id, $redirect_to ) );
557 }
558 /**
559 * Return the link to the topic
560 *
561 * @since 2.0.0 bbPress (r2485)
562 *
563 * @param int $topic_id Optional. Topic id
564 * @param string $redirect_to Optional. Pass a redirect value for use with
565 * shortcodes and other fun things.
566 * @return string Permanent link to topic
567 */
568 function bbp_get_topic_permalink( $topic_id = 0, $redirect_to = '' ) {
569 $topic_id = bbp_get_topic_id( $topic_id );
570
571 // Use the redirect address
572 if ( ! empty( $redirect_to ) ) {
573 $topic_permalink = esc_url_raw( $redirect_to );
574
575 // Use the topic permalink
576 } else {
577 $topic_permalink = get_permalink( $topic_id );
578 }
579
580 // Filter & return
581 return apply_filters( 'bbp_get_topic_permalink', $topic_permalink, $topic_id );
582 }
583
584 /**
585 * Output the title of the topic
586 *
587 * @since 2.0.0 bbPress (r2485)
588 *
589 * @param int $topic_id Optional. Topic id
590 */
591 function bbp_topic_title( $topic_id = 0 ) {
592 echo bbp_get_topic_title( $topic_id );
593 }
594 /**
595 * Return the title of the topic
596 *
597 * @since 2.0.0 bbPress (r2485)
598 *
599 * @param int $topic_id Optional. Topic id
600 * @return string Title of topic
601 */
602 function bbp_get_topic_title( $topic_id = 0 ) {
603 $topic_id = bbp_get_topic_id( $topic_id );
604 $title = get_the_title( $topic_id );
605
606 // Filter & return
607 return apply_filters( 'bbp_get_topic_title', $title, $topic_id );
608 }
609
610 /**
611 * Output the topic archive title
612 *
613 * @since 2.0.0 bbPress (r3249)
614 *
615 * @param string $title Default text to use as title
616 */
617 function bbp_topic_archive_title( $title = '' ) {
618 echo bbp_get_topic_archive_title( $title );
619 }
620 /**
621 * Return the topic archive title
622 *
623 * @since 2.0.0 bbPress (r3249)
624 *
625 * @param string $title Default text to use as title
626 *
627 * @return string The topic archive title
628 */
629 function bbp_get_topic_archive_title( $title = '' ) {
630
631 // If no title was passed
632 if ( empty( $title ) ) {
633
634 // Set root text to page title
635 $page = bbp_get_page_by_path( bbp_get_topic_archive_slug() );
636 if ( ! empty( $page ) ) {
637 $title = get_the_title( $page->ID );
638
639 // Default to topic post type name label
640 } else {
641 $tto = get_post_type_object( bbp_get_topic_post_type() );
642 $title = $tto->labels->name;
643 }
644 }
645
646 // Filter & return
647 return apply_filters( 'bbp_get_topic_archive_title', $title );
648 }
649
650 /**
651 * Output the content of the topic
652 *
653 * @since 2.0.0 bbPress (r2780)
654 *
655 * @param int $topic_id Optional. Topic id
656 */
657 function bbp_topic_content( $topic_id = 0 ) {
658 echo bbp_get_topic_content( $topic_id );
659 }
660 /**
661 * Return the content of the topic
662 *
663 * @since 2.0.0 bbPress (r2780)
664 *
665 * @param int $topic_id Optional. Topic id
666 * @return string Content of the topic
667 */
668 function bbp_get_topic_content( $topic_id = 0 ) {
669 $topic_id = bbp_get_topic_id( $topic_id );
670
671 // Check if password is required
672 if ( post_password_required( $topic_id ) ) {
673 return get_the_password_form();
674 }
675
676 $content = get_post_field( 'post_content', $topic_id );
677
678 // Filter & return
679 return apply_filters( 'bbp_get_topic_content', $content, $topic_id );
680 }
681
682 /**
683 * Output the excerpt of the topic
684 *
685 * @since 2.0.0 bbPress (r2780)
686 *
687 * @param int $topic_id Optional. Topic id
688 * @param int $length Optional. Length of the excerpt. Defaults to 100 letters
689 */
690 function bbp_topic_excerpt( $topic_id = 0, $length = 100 ) {
691 echo bbp_get_topic_excerpt( $topic_id, $length );
692 }
693 /**
694 * Return the excerpt of the topic
695 *
696 * @since 2.0.0 bbPress (r2780)
697 *
698 * @param int $topic_id Optional. topic id
699 * @param int $length Optional. Length of the excerpt. Defaults to 100
700 * letters
701 * @return string topic Excerpt
702 */
703 function bbp_get_topic_excerpt( $topic_id = 0, $length = 100 ) {
704 $topic_id = bbp_get_topic_id( $topic_id );
705 $length = (int) $length;
706 $excerpt = get_post_field( 'post_excerpt', $topic_id );
707
708 if ( empty( $excerpt ) ) {
709 $excerpt = bbp_get_topic_content( $topic_id );
710 }
711
712 $excerpt = trim( strip_tags( $excerpt ) );
713
714 // Multibyte support
715 if ( function_exists( 'mb_strlen' ) ) {
716 $excerpt_length = mb_strlen( $excerpt );
717 } else {
718 $excerpt_length = strlen( $excerpt );
719 }
720
721 if ( ! empty( $length ) && ( $excerpt_length > $length ) ) {
722 $excerpt = mb_substr( $excerpt, 0, $length - 1 );
723 $excerpt .= '&hellip;';
724 }
725
726 // Filter & return
727 return apply_filters( 'bbp_get_topic_excerpt', $excerpt, $topic_id, $length );
728 }
729
730 /**
731 * Output the post date and time of a topic
732 *
733 * @since 2.2.0 bbPress (r4155)
734 *
735 * @param int $topic_id Optional. Topic id.
736 * @param bool $humanize Optional. Humanize output using time_since
737 * @param bool $gmt Optional. Use GMT
738 */
739 function bbp_topic_post_date( $topic_id = 0, $humanize = false, $gmt = false ) {
740 echo bbp_get_topic_post_date( $topic_id, $humanize, $gmt );
741 }
742 /**
743 * Return the post date and time of a topic
744 *
745 * @since 2.2.0 bbPress (r4155)
746 *
747 * @param int $topic_id Optional. Topic id.
748 * @param bool $humanize Optional. Humanize output using time_since
749 * @param bool $gmt Optional. Use GMT
750 * @return string
751 */
752 function bbp_get_topic_post_date( $topic_id = 0, $humanize = false, $gmt = false ) {
753 $topic_id = bbp_get_topic_id( $topic_id );
754
755 // 4 days, 4 hours ago
756 if ( ! empty( $humanize ) ) {
757 $gmt_s = ! empty( $gmt ) ? 'G' : 'U';
758 $date = get_post_time( $gmt_s, $gmt, $topic_id );
759 $time = false; // For filter below
760 $result = bbp_get_time_since( $date );
761
762 // August 4, 2012 at 2:37 pm
763 } else {
764 $date = get_post_time( get_option( 'date_format' ), $gmt, $topic_id, true );
765 $time = get_post_time( get_option( 'time_format' ), $gmt, $topic_id, true );
766 $result = sprintf( _x( '%1$s at %2$s', 'date at time', 'bbpress' ), $date, $time );
767 }
768
769 // Filter & return
770 return apply_filters( 'bbp_get_topic_post_date', $result, $topic_id, $humanize, $gmt, $date, $time );
771 }
772
773 /**
774 * Output pagination links of a topic within the topic loop
775 *
776 * @since 2.0.0 bbPress (r2966)
777 *
778 * @param array $args See {@link bbp_get_topic_pagination()}
779 */
780 function bbp_topic_pagination( $args = array() ) {
781 echo bbp_get_topic_pagination( $args );
782 }
783 /**
784 * Returns pagination links of a topic within the topic loop
785 *
786 * @since 2.0.0 bbPress (r2966)
787 *
788 * @param array $args This function supports these arguments:
789 * - topic_id: Topic id
790 * - before: Before the links
791 * - after: After the links
792 * @return string Pagination links
793 */
794 function bbp_get_topic_pagination( $args = array() ) {
795
796 // Bail if threading replies
797 if ( bbp_thread_replies() ) {
798 return;
799 }
800
801 // Parse arguments against default values
802 $r = bbp_parse_args( $args, array(
803 'topic_id' => bbp_get_topic_id(),
804 'before' => '<span class="bbp-topic-pagination">',
805 'after' => '</span>',
806 ), 'get_topic_pagination' );
807
808 // Slug must be checked for topics that have never been approved/published
809 $has_slug = bbp_get_topic( $r['topic_id'] )->post_name;
810
811 // If pretty permalinks are enabled, make our pagination pretty
812 $base = ! empty( $has_slug ) && bbp_use_pretty_urls() && bbp_is_topic_public( $r['topic_id'] )
813 ? trailingslashit( get_permalink( $r['topic_id'] ) ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' )
814 : add_query_arg( 'paged', '%#%', get_permalink( $r['topic_id'] ) );
815
816 // Get total and add 1 if topic is included in the reply loop
817 $total = bbp_get_topic_reply_count( $r['topic_id'], true );
818
819 // Bump if topic is in loop
820 if ( ! bbp_show_lead_topic() ) {
821 $total++;
822 }
823
824 // Total for pagination boundaries
825 $total_pages = ceil( $total / bbp_get_replies_per_page() );
826
827 // Maybe add view-all args
828 $add_args = bbp_get_view_all( 'edit_others_replies' )
829 ? array( 'view' => 'all' )
830 : false;
831
832 // Pagination settings with filter
833 $bbp_topic_pagination = apply_filters( 'bbp_get_topic_pagination', array(
834 'base' => $base,
835 'total' => $total_pages,
836 'current' => 0,
837 'prev_next' => false,
838 'mid_size' => 2,
839 'end_size' => 2,
840 'add_args' => $add_args
841 ) );
842
843 // Add pagination to query object
844 $pagination_links = bbp_paginate_links( $bbp_topic_pagination );
845
846 // Maybe add before and after to pagination links
847 if ( ! empty( $pagination_links ) ) {
848 $pagination_links = $r['before'] . $pagination_links . $r['after'];
849 }
850
851 // Filter & return
852 return apply_filters( 'bbp_get_topic_pagination', $pagination_links, $args );
853 }
854
855 /**
856 * Append revisions to the topic content
857 *
858 * @since 2.0.0 bbPress (r2782)
859 *
860 * @param string $content Optional. Content to which we need to append the revisions to
861 * @param int $topic_id Optional. Topic id
862 * @return string Content with the revisions appended
863 */
864 function bbp_topic_content_append_revisions( $content = '', $topic_id = 0 ) {
865
866 // Bail if in admin or feed
867 if ( is_admin() || is_feed() ) {
868 return;
869 }
870
871 // Validate the ID
872 $topic_id = bbp_get_topic_id( $topic_id );
873
874 // Filter & return
875 return apply_filters( 'bbp_topic_append_revisions', $content . bbp_get_topic_revision_log( $topic_id ), $content, $topic_id );
876 }
877
878 /**
879 * Output the revision log of the topic
880 *
881 * @since 2.0.0 bbPress (r2782)
882 *
883 * @param int $topic_id Optional. Topic id
884 */
885 function bbp_topic_revision_log( $topic_id = 0 ) {
886 echo bbp_get_topic_revision_log( $topic_id );
887 }
888 /**
889 * Return the formatted revision log of the topic
890 *
891 * @since 2.0.0 bbPress (r2782)
892 *
893 * @param int $topic_id Optional. Topic id
894 * @return string Revision log of the topic
895 */
896 function bbp_get_topic_revision_log( $topic_id = 0 ) {
897
898 // Create necessary variables
899 $topic_id = bbp_get_topic_id( $topic_id );
900 $revision_log = bbp_get_topic_raw_revision_log( $topic_id );
901
902 if ( empty( $topic_id ) || empty( $revision_log ) || ! is_array( $revision_log ) ) {
903 return false;
904 }
905
906 $revisions = bbp_get_topic_revisions( $topic_id );
907 if ( empty( $revisions ) ) {
908 return false;
909 }
910
911 $retval = "\n\n" . '<ul id="bbp-topic-revision-log-' . esc_attr( $topic_id ) . '" class="bbp-topic-revision-log">' . "\n\n";
912
913 // Loop through revisions
914 foreach ( (array) $revisions as $revision ) {
915
916 if ( empty( $revision_log[ $revision->ID ] ) ) {
917 $author_id = $revision->post_author;
918 $reason = '';
919 } else {
920 $author_id = $revision_log[ $revision->ID ]['author'];
921 $reason = $revision_log[ $revision->ID ]['reason'];
922 }
923
924 $author = bbp_get_author_link( array( 'size' => 14, 'link_text' => bbp_get_topic_author_display_name( $revision->ID ), 'post_id' => $revision->ID ) );
925 $since = bbp_get_time_since( bbp_convert_date( $revision->post_modified ) );
926
927 $retval .= "\t" . '<li id="bbp-topic-revision-log-' . esc_attr( $topic_id ) . '-item-' . esc_attr( $revision->ID ) . '" class="bbp-topic-revision-log-item">' . "\n";
928 if ( ! empty( $reason ) ) {
929 $retval .= "\t\t" . sprintf( esc_html__( 'This topic was modified %1$s by %2$s. Reason: %3$s', 'bbpress' ), esc_html( $since ), $author, esc_html( $reason ) ) . "\n";
930 } else {
931 $retval .= "\t\t" . sprintf( esc_html__( 'This topic was modified %1$s by %2$s.', 'bbpress' ), esc_html( $since ), $author ) . "\n";
932 }
933 $retval .= "\t" . '</li>' . "\n";
934 }
935
936 $retval .= "\n" . '</ul>' . "\n\n";
937
938 // Filter & return
939 return apply_filters( 'bbp_get_topic_revision_log', $retval, $topic_id );
940 }
941 /**
942 * Return the raw revision log of the topic
943 *
944 * @since 2.0.0 bbPress (r2782)
945 *
946 * @param int $topic_id Optional. Topic id
947 * @return string Raw revision log of the topic
948 */
949 function bbp_get_topic_raw_revision_log( $topic_id = 0 ) {
950 $topic_id = bbp_get_topic_id( $topic_id );
951
952 $revision_log = get_post_meta( $topic_id, '_bbp_revision_log', true );
953 $revision_log = ! empty( $revision_log )
954 ? $revision_log
955 : array();
956
957 // Filter & return
958 return apply_filters( 'bbp_get_topic_raw_revision_log', $revision_log, $topic_id );
959 }
960
961 /**
962 * Return the revisions of the topic
963 *
964 * @since 2.0.0 bbPress (r2782)
965 *
966 * @param int $topic_id Optional. Topic id
967 * @return WP_Post[]|int[] Topic revisions
968 */
969 function bbp_get_topic_revisions( $topic_id = 0 ) {
970 $topic_id = bbp_get_topic_id( $topic_id );
971 $revisions = wp_get_post_revisions( $topic_id, array( 'order' => 'ASC' ) );
972
973 // Filter & return
974 return apply_filters( 'bbp_get_topic_revisions', $revisions, $topic_id );
975 }
976
977 /**
978 * Return the revision count of the topic
979 *
980 * @since 2.0.0 bbPress (r2782)
981 *
982 * @param int $topic_id Optional. Topic id
983 * @return string Topic revision count
984 */
985 function bbp_get_topic_revision_count( $topic_id = 0, $integer = false ) {
986 $topic_id = bbp_get_topic_id( $topic_id );
987 $count = count( bbp_get_topic_revisions( $topic_id ) );
988 $filter = ( true === $integer )
989 ? 'bbp_get_topic_revision_count_int'
990 : 'bbp_get_topic_revision_count';
991
992 return apply_filters( $filter, $count, $topic_id );
993 }
994
995 /**
996 * Is the topic a sticky or super sticky?
997 *
998 * @since 2.0.0 bbPress (r2754)
999 *
1000 * @param int $topic_id Optional. Topic id
1001 * @param int $check_super Optional. If set to true and if the topic is not a
1002 * normal sticky, it is checked if it is a super
1003 * sticky or not. Defaults to true.
1004 * @return bool True if sticky or super sticky, false if not.
1005 */
1006 function bbp_is_topic_sticky( $topic_id = 0, $check_super = true ) {
1007 $topic_id = bbp_get_topic_id( $topic_id );
1008 $forum_id = bbp_get_topic_forum_id( $topic_id );
1009 $stickies = bbp_get_stickies( $forum_id );
1010 $retval = in_array( $topic_id, $stickies, true );
1011
1012 // Maybe check super stickies
1013 if ( ( false === $retval ) && ( true === $check_super ) ) {
1014 $retval = bbp_is_topic_super_sticky( $topic_id );
1015 }
1016
1017 // Filter & return
1018 return (bool) apply_filters( 'bbp_is_topic_sticky', $retval, $topic_id, $check_super );
1019 }
1020
1021 /**
1022 * Is the topic a super sticky?
1023 *
1024 * @since 2.0.0 bbPress (r2754)
1025 *
1026 * @param int $topic_id Optional. Topic id
1027 * @return bool True if super sticky, false if not.
1028 */
1029 function bbp_is_topic_super_sticky( $topic_id = 0 ) {
1030 $topic_id = bbp_get_topic_id( $topic_id );
1031 $stickies = bbp_get_super_stickies( $topic_id );
1032 $retval = in_array( $topic_id, $stickies, true );
1033
1034 // Filter & return
1035 return (bool) apply_filters( 'bbp_is_topic_super_sticky', $retval, $topic_id );
1036 }
1037
1038 /**
1039 * Output the status of the topic
1040 *
1041 * @since 2.0.0 bbPress (r2667)
1042 *
1043 * @param int $topic_id Optional. Topic id
1044 */
1045 function bbp_topic_status( $topic_id = 0 ) {
1046 echo bbp_get_topic_status( $topic_id );
1047 }
1048 /**
1049 * Return the status of the topic
1050 *
1051 * @since 2.0.0 bbPress (r2667)
1052 *
1053 * @param int $topic_id Optional. Topic id
1054 * @return string Status of topic
1055 */
1056 function bbp_get_topic_status( $topic_id = 0 ) {
1057 $topic_id = bbp_get_topic_id( $topic_id );
1058
1059 // Filter & return
1060 return apply_filters( 'bbp_get_topic_status', get_post_status( $topic_id ), $topic_id );
1061 }
1062
1063 /**
1064 * Is the topic closed to new replies?
1065 *
1066 * @since 2.0.0 bbPress (r2746)
1067 *
1068 * @param int $topic_id Optional. Topic id
1069 *
1070 * @return bool True if closed, false if not.
1071 */
1072 function bbp_is_topic_closed( $topic_id = 0 ) {
1073 $topic_id = bbp_get_topic_id( $topic_id );
1074 $status = bbp_get_closed_status_id();
1075 $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1076
1077 // Filter & return
1078 return (bool) apply_filters( 'bbp_is_topic_closed', $topic_status, $topic_id );
1079 }
1080
1081 /**
1082 * Is the topic open to new replies?
1083 *
1084 * @since 2.0.0 bbPress (r2727)
1085 *
1086 * @param int $topic_id Optional. Topic id
1087 *
1088 * @return bool True if open, false if closed.
1089 */
1090 function bbp_is_topic_open( $topic_id = 0 ) {
1091 return ! bbp_is_topic_closed( $topic_id );
1092 }
1093
1094 /**
1095 * Is the topic publicly viewable?
1096 *
1097 * See bbp_get_public_topic_statuses() for public statuses.
1098 *
1099 * @since 2.6.0 bbPress (r6383)
1100 *
1101 * @param int $topic_id Optional. Topic id
1102 * @return bool True if public, false if not.
1103 */
1104 function bbp_is_topic_public( $topic_id = 0 ) {
1105 $topic_id = bbp_get_topic_id( $topic_id );
1106 $status = bbp_get_topic_status( $topic_id );
1107 $public = bbp_get_public_topic_statuses();
1108 $is_public = in_array( $status, $public, true );
1109
1110 // Filter & return
1111 return (bool) apply_filters( 'bbp_is_topic_public', $is_public, $topic_id );
1112 }
1113
1114 /**
1115 * Does the topic have a published status?
1116 *
1117 * @since 2.0.0 bbPress (r3496)
1118 *
1119 * @param int $topic_id Optional. Topic id
1120 * @return bool True if published, false if not.
1121 */
1122 function bbp_is_topic_published( $topic_id = 0 ) {
1123 $topic_id = bbp_get_topic_id( $topic_id );
1124 $status = bbp_get_public_status_id();
1125 $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1126
1127 // Filter & return
1128 return (bool) apply_filters( 'bbp_is_topic_published', $topic_status, $topic_id );
1129 }
1130
1131 /**
1132 * Is the topic marked as spam?
1133 *
1134 * @since 2.0.0 bbPress (r2727)
1135 *
1136 * @param int $topic_id Optional. Topic id
1137 * @return bool True if spam, false if not.
1138 */
1139 function bbp_is_topic_spam( $topic_id = 0 ) {
1140 $topic_id = bbp_get_topic_id( $topic_id );
1141 $status = bbp_get_spam_status_id();
1142 $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1143
1144 // Filter & return
1145 return (bool) apply_filters( 'bbp_is_topic_spam', $topic_status, $topic_id );
1146 }
1147
1148 /**
1149 * Is the topic trashed?
1150 *
1151 * @since 2.0.0 bbPress (r2888)
1152 *
1153 * @param int $topic_id Optional. Topic id
1154 * @return bool True if trashed, false if not.
1155 */
1156 function bbp_is_topic_trash( $topic_id = 0 ) {
1157 $topic_id = bbp_get_topic_id( $topic_id );
1158 $status = bbp_get_trash_status_id();
1159 $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1160
1161 // Filter & return
1162 return (bool) apply_filters( 'bbp_is_topic_trash', $topic_status, $topic_id );
1163 }
1164
1165 /**
1166 * Is the topic pending?
1167 *
1168 * @since 2.6.0 bbPress (r5504)
1169 *
1170 * @param int $topic_id Optional. Topic id
1171 * @return bool True if pending, false if not.
1172 */
1173 function bbp_is_topic_pending( $topic_id = 0 ) {
1174 $topic_id = bbp_get_topic_id( $topic_id );
1175 $status = bbp_get_pending_status_id();
1176 $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1177
1178 // Filter & return
1179 return (bool) apply_filters( 'bbp_is_topic_pending', $topic_status, $topic_id );
1180 }
1181
1182 /**
1183 * Is the topic private?
1184 *
1185 * @since 2.6.0 bbPress (r5504)
1186 *
1187 * @param int $topic_id Optional. Topic id
1188 * @return bool True if private, false if not.
1189 */
1190 function bbp_is_topic_private( $topic_id = 0 ) {
1191 $topic_id = bbp_get_topic_id( $topic_id );
1192 $status = bbp_get_private_status_id();
1193 $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1194
1195 // Filter & return
1196 return (bool) apply_filters( 'bbp_is_topic_private', $topic_status, $topic_id );
1197 }
1198
1199 /**
1200 * Is the posted by an anonymous user?
1201 *
1202 * @since 2.0.0 bbPress (r2753)
1203 *
1204 * @param int $topic_id Optional. Topic id
1205 * @return bool True if the post is by an anonymous user, false if not.
1206 */
1207 function bbp_is_topic_anonymous( $topic_id = 0 ) {
1208 $topic_id = bbp_get_topic_id( $topic_id );
1209 $retval = false;
1210
1211 if ( ! bbp_get_topic_author_id( $topic_id ) ) {
1212 $retval = true;
1213
1214 } elseif ( get_post_meta( $topic_id, '_bbp_anonymous_name', true ) ) {
1215 $retval = true;
1216
1217 } elseif ( get_post_meta( $topic_id, '_bbp_anonymous_email', true ) ) {
1218 $retval = true;
1219 }
1220
1221 // Filter & return
1222 return (bool) apply_filters( 'bbp_is_topic_anonymous', $retval, $topic_id );
1223 }
1224
1225 /**
1226 * Deprecated. Use bbp_topic_author_display_name() instead.
1227 *
1228 * Output the author of the topic.
1229 *
1230 * @since 2.0.0 bbPress (r2590)
1231 *
1232 * @deprecated 2.5.0 bbPress (r5119)
1233 *
1234 * @param int $topic_id Optional. Topic id
1235 */
1236 function bbp_topic_author( $topic_id = 0 ) {
1237 echo bbp_get_topic_author( $topic_id );
1238 }
1239 /**
1240 * Deprecated. Use bbp_get_topic_author_display_name() instead.
1241 *
1242 * Return the author of the topic
1243 *
1244 * @since 2.0.0 bbPress (r2590)
1245 *
1246 * @deprecated 2.5.0 bbPress (r5119)
1247 *
1248 * @param int $topic_id Optional. Topic id
1249 * @return string Author of topic
1250 */
1251 function bbp_get_topic_author( $topic_id = 0 ) {
1252 $topic_id = bbp_get_topic_id( $topic_id );
1253
1254 if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1255 $author = get_the_author_meta( 'display_name', bbp_get_topic_author_id( $topic_id ) );
1256 } else {
1257 $author = get_post_meta( $topic_id, '_bbp_anonymous_name', true );
1258 }
1259
1260 // Filter & return
1261 return apply_filters( 'bbp_get_topic_author', $author, $topic_id );
1262 }
1263
1264 /**
1265 * Output the author ID of the topic
1266 *
1267 * @since 2.0.0 bbPress (r2590)
1268 *
1269 * @param int $topic_id Optional. Topic id
1270 */
1271 function bbp_topic_author_id( $topic_id = 0 ) {
1272 echo bbp_get_topic_author_id( $topic_id );
1273 }
1274 /**
1275 * Return the author ID of the topic
1276 *
1277 * @since 2.0.0 bbPress (r2590)
1278 *
1279 * @param int $topic_id Optional. Topic id
1280 * @return string Author of topic
1281 */
1282 function bbp_get_topic_author_id( $topic_id = 0 ) {
1283 $topic_id = bbp_get_topic_id( $topic_id );
1284 $author_id = get_post_field( 'post_author', $topic_id );
1285
1286 // Filter & return
1287 return (int) apply_filters( 'bbp_get_topic_author_id', (int) $author_id, $topic_id );
1288 }
1289
1290 /**
1291 * Output the author display_name of the topic
1292 *
1293 * @since 2.0.0 bbPress (r2590)
1294 *
1295 * @param int $topic_id Optional. Topic id
1296 */
1297 function bbp_topic_author_display_name( $topic_id = 0 ) {
1298 echo bbp_get_topic_author_display_name( $topic_id );
1299 }
1300 /**
1301 * Return the author display_name of the topic
1302 *
1303 * @since 2.0.0 bbPress (r2485)
1304 *
1305 * @param int $topic_id Optional. Topic id
1306 * @return string Topic's author's display name
1307 */
1308 function bbp_get_topic_author_display_name( $topic_id = 0 ) {
1309 $topic_id = bbp_get_topic_id( $topic_id );
1310
1311 // Check for anonymous user
1312 if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1313
1314 // Get the author ID
1315 $author_id = bbp_get_topic_author_id( $topic_id );
1316
1317 // Try to get a display name
1318 $author_name = get_the_author_meta( 'display_name', $author_id );
1319
1320 // Fall back to user login
1321 if ( empty( $author_name ) ) {
1322 $author_name = get_the_author_meta( 'user_login', $author_id );
1323 }
1324
1325 // User does not have an account
1326 } else {
1327 $author_name = get_post_meta( $topic_id, '_bbp_anonymous_name', true );
1328 }
1329
1330 // Fallback if nothing could be found
1331 if ( empty( $author_name ) ) {
1332 $author_name = bbp_get_fallback_display_name( $topic_id );
1333 }
1334
1335 // Filter & return
1336 return apply_filters( 'bbp_get_topic_author_display_name', $author_name, $topic_id );
1337 }
1338
1339 /**
1340 * Output the author avatar of the topic
1341 *
1342 * @since 2.0.0 bbPress (r2590)
1343 *
1344 * @param int $topic_id Optional. Topic id
1345 * @param int $size Optional. Avatar size. Defaults to 40
1346 */
1347 function bbp_topic_author_avatar( $topic_id = 0, $size = 40 ) {
1348 echo bbp_get_topic_author_avatar( $topic_id, $size );
1349 }
1350 /**
1351 * Return the author avatar of the topic
1352 *
1353 * @since 2.0.0 bbPress (r2590)
1354 *
1355 * @param int $topic_id Optional. Topic id
1356 * @param int $size Optional. Avatar size. Defaults to 40
1357 * @return string Avatar of the author of the topic
1358 */
1359 function bbp_get_topic_author_avatar( $topic_id = 0, $size = 40 ) {
1360 $author_avatar = '';
1361
1362 $topic_id = bbp_get_topic_id( $topic_id );
1363 if ( ! empty( $topic_id ) ) {
1364 if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1365 $author_avatar = get_avatar( bbp_get_topic_author_id( $topic_id ), $size );
1366 } else {
1367 $author_avatar = get_avatar( get_post_meta( $topic_id, '_bbp_anonymous_email', true ), $size );
1368 }
1369 }
1370
1371 // Filter & return
1372 return apply_filters( 'bbp_get_topic_author_avatar', $author_avatar, $topic_id, $size );
1373 }
1374
1375 /**
1376 * Output the author link of the topic
1377 *
1378 * @since 2.0.0 bbPress (r2717)
1379 *
1380 * @param mixed|int $args If it is an integer, it is used as topic_id. Optional.
1381 */
1382 function bbp_topic_author_link( $args = array() ) {
1383 echo bbp_get_topic_author_link( $args );
1384 }
1385 /**
1386 * Return the author link of the topic
1387 *
1388 * @since 2.0.0 bbPress (r2717)
1389 *
1390 * @param mixed|int $args If it is an integer, it is used as topic id.
1391 * Optional.
1392 * @return string Author link of topic
1393 */
1394 function bbp_get_topic_author_link( $args = array() ) {
1395
1396 // Parse arguments against default values
1397 $r = bbp_parse_args( $args, array(
1398 'post_id' => 0,
1399 'link_title' => '',
1400 'type' => 'both',
1401 'size' => 80,
1402 'sep' => '',
1403 'show_role' => false
1404 ), 'get_topic_author_link' );
1405
1406 // Default return value
1407 $author_link = '';
1408
1409 // Used as topic_id
1410 $topic_id = is_numeric( $args )
1411 ? bbp_get_topic_id( $args )
1412 : bbp_get_topic_id( $r['post_id'] );
1413
1414 // Topic ID is good
1415 if ( ! empty( $topic_id ) ) {
1416
1417 // Get some useful topic information
1418 $author_url = bbp_get_topic_author_url( $topic_id );
1419 $anonymous = bbp_is_topic_anonymous( $topic_id );
1420
1421 // Tweak link title if empty
1422 if ( empty( $r['link_title'] ) ) {
1423 $author = bbp_get_topic_author_display_name( $topic_id );
1424 $title = empty( $anonymous )
1425 ? esc_attr__( "View %s's profile", 'bbpress' )
1426 : esc_attr__( "Visit %s's website", 'bbpress' );
1427
1428 $link_title = sprintf( $title, $author );
1429
1430 // Use what was passed if not
1431 } else {
1432 $link_title = $r['link_title'];
1433 }
1434
1435 // Setup title and author_links array
1436 $author_links = array();
1437 $link_title = ! empty( $link_title )
1438 ? ' title="' . esc_attr( $link_title ) . '"'
1439 : '';
1440
1441 // Get avatar (unescaped, because HTML)
1442 if ( ( 'avatar' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1443 $author_links['avatar'] = bbp_get_topic_author_avatar( $topic_id, $r['size'] );
1444 }
1445
1446 // Get display name (escaped, because never HTML)
1447 if ( ( 'name' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1448 $author_links['name'] = esc_html( bbp_get_topic_author_display_name( $topic_id ) );
1449 }
1450
1451 // Empty array
1452 $links = array();
1453 $sprint = '<span %1$s>%2$s</span>';
1454
1455 // Wrap each link
1456 foreach ( $author_links as $link => $link_text ) {
1457 $link_class = ' class="bbp-author-' . esc_attr( $link ) . '"';
1458 $links[] = sprintf( $sprint, $link_class, $link_text );
1459 }
1460
1461 // Juggle
1462 $author_links = $links;
1463 unset( $links );
1464
1465 // Filter sections
1466 $sections = apply_filters( 'bbp_get_topic_author_links', $author_links, $r, $args );
1467
1468 // Assemble sections into author link
1469 $author_link = implode( $r['sep'], $sections );
1470
1471 // Only wrap in link if profile exists
1472 if ( empty( $anonymous ) && bbp_user_has_profile( bbp_get_topic_author_id( $topic_id ) ) ) {
1473 $author_link = sprintf( '<a href="%1$s"%2$s%3$s>%4$s</a>', esc_url( $author_url ), $link_title, ' class="bbp-author-link"', $author_link );
1474 }
1475
1476 // Role is not linked
1477 if ( true === $r['show_role'] ) {
1478 $author_link .= bbp_get_topic_author_role( array( 'topic_id' => $topic_id ) );
1479 }
1480 }
1481
1482 // Filter & return
1483 return apply_filters( 'bbp_get_topic_author_link', $author_link, $r, $args );
1484 }
1485
1486 /**
1487 * Output the author url of the topic
1488 *
1489 * @since 2.0.0 bbPress (r2590)
1490 *
1491 * @param int $topic_id Optional. Topic id
1492 */
1493 function bbp_topic_author_url( $topic_id = 0 ) {
1494 echo esc_url( bbp_get_topic_author_url( $topic_id ) );
1495 }
1496
1497 /**
1498 * Return the author url of the topic
1499 *
1500 * @since 2.0.0 bbPress (r2590)
1501 *
1502 * @param int $topic_id Optional. Topic id
1503 * @return string Author URL of topic
1504 */
1505 function bbp_get_topic_author_url( $topic_id = 0 ) {
1506 $topic_id = bbp_get_topic_id( $topic_id );
1507
1508 // Check for anonymous user or non-existant user
1509 if ( ! bbp_is_topic_anonymous( $topic_id ) && bbp_user_has_profile( bbp_get_topic_author_id( $topic_id ) ) ) {
1510 $author_url = bbp_get_user_profile_url( bbp_get_topic_author_id( $topic_id ) );
1511 } else {
1512 $author_url = get_post_meta( $topic_id, '_bbp_anonymous_website', true );
1513
1514 // Set empty author_url as empty string
1515 if ( empty( $author_url ) ) {
1516 $author_url = '';
1517 }
1518 }
1519
1520 // Filter & return
1521 return apply_filters( 'bbp_get_topic_author_url', $author_url, $topic_id );
1522 }
1523
1524 /**
1525 * Output the topic author email address
1526 *
1527 * @since 2.0.0 bbPress (r3445)
1528 *
1529 * @param int $topic_id Optional. Reply id
1530 */
1531 function bbp_topic_author_email( $topic_id = 0 ) {
1532 echo bbp_get_topic_author_email( $topic_id );
1533 }
1534 /**
1535 * Return the topic author email address
1536 *
1537 * @since 2.0.0 bbPress (r3445)
1538 *
1539 * @param int $topic_id Optional. Reply id
1540 * @return string Topic author email address
1541 */
1542 function bbp_get_topic_author_email( $topic_id = 0 ) {
1543 $topic_id = bbp_get_topic_id( $topic_id );
1544
1545 // Not anonymous user
1546 if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1547
1548 // Use topic author email address
1549 $user_id = bbp_get_topic_author_id( $topic_id );
1550 $user = get_userdata( $user_id );
1551 $author_email = ! empty( $user->user_email ) ? $user->user_email : '';
1552
1553 // Anonymous
1554 } else {
1555
1556 // Get email from post meta
1557 $author_email = get_post_meta( $topic_id, '_bbp_anonymous_email', true );
1558
1559 // Sanity check for missing email address
1560 if ( empty( $author_email ) ) {
1561 $author_email = '';
1562 }
1563 }
1564
1565 // Filter & return
1566 return apply_filters( 'bbp_get_topic_author_email', $author_email, $topic_id );
1567 }
1568
1569 /**
1570 * Output the topic author role
1571 *
1572 * @since 2.1.0 bbPress (r3860)
1573 *
1574 * @param array $args Optional.
1575 */
1576 function bbp_topic_author_role( $args = array() ) {
1577 echo bbp_get_topic_author_role( $args );
1578 }
1579 /**
1580 * Return the topic author role
1581 *
1582 * @since 2.1.0 bbPress (r3860)
1583 *
1584 * @param array $args Optional.
1585 * @return string topic author role
1586 */
1587 function bbp_get_topic_author_role( $args = array() ) {
1588
1589 // Parse arguments against default values
1590 $r = bbp_parse_args( $args, array(
1591 'topic_id' => 0,
1592 'class' => false,
1593 'before' => '<div class="bbp-author-role">',
1594 'after' => '</div>'
1595 ), 'get_topic_author_role' );
1596
1597 $topic_id = bbp_get_topic_id( $r['topic_id'] );
1598 $role = bbp_get_user_display_role( bbp_get_topic_author_id( $topic_id ) );
1599
1600 // Backwards compatibilty with old 'class' argument
1601 if ( ! empty( $r['class'] ) ) {
1602 $author_role = sprintf( '%1$s<div class="%2$s">%3$s</div>%4$s', $r['before'], $r['class'], $role, $r['after'] );
1603
1604 // Simpler before & after arguments
1605 // https://bbpress.trac.wordpress.org/ticket/2557
1606 } else {
1607 $author_role = $r['before'] . $role . $r['after'];
1608 }
1609
1610 // Filter & return
1611 return apply_filters( 'bbp_get_topic_author_role', $author_role, $r );
1612 }
1613
1614
1615 /**
1616 * Output the title of the forum a topic belongs to
1617 *
1618 * @since 2.0.0 bbPress (r2485)
1619 *
1620 * @param int $topic_id Optional. Topic id
1621 */
1622 function bbp_topic_forum_title( $topic_id = 0 ) {
1623 echo bbp_get_topic_forum_title( $topic_id );
1624 }
1625 /**
1626 * Return the title of the forum a topic belongs to
1627 *
1628 * @since 2.0.0 bbPress (r2485)
1629 *
1630 * @param int $topic_id Optional. Topic id
1631 * @return string Topic forum title
1632 */
1633 function bbp_get_topic_forum_title( $topic_id = 0 ) {
1634 $topic_id = bbp_get_topic_id( $topic_id );
1635 $forum_id = bbp_get_topic_forum_id( $topic_id );
1636
1637 // Filter & return
1638 return apply_filters( 'bbp_get_topic_forum', bbp_get_forum_title( $forum_id ), $topic_id, $forum_id );
1639 }
1640
1641 /**
1642 * Output the forum id a topic belongs to
1643 *
1644 * @since 2.0.0 bbPress (r2491)
1645 *
1646 * @param int $topic_id Optional. Topic id
1647 */
1648 function bbp_topic_forum_id( $topic_id = 0 ) {
1649 echo bbp_get_topic_forum_id( $topic_id );
1650 }
1651 /**
1652 * Return the forum id a topic belongs to
1653 *
1654 * @since 2.0.0 bbPress (r2491)
1655 *
1656 * @param int $topic_id Optional. Topic id
1657 * @return int Topic forum id
1658 */
1659 function bbp_get_topic_forum_id( $topic_id = 0 ) {
1660 $topic_id = bbp_get_topic_id( $topic_id );
1661 $forum_id = (int) get_post_field( 'post_parent', $topic_id );
1662
1663 // Meta-data fallback
1664 if ( empty( $forum_id ) ) {
1665 $forum_id = (int) get_post_meta( $topic_id, '_bbp_forum_id', true );
1666 }
1667
1668 // Filter
1669 if ( ! empty( $forum_id ) ) {
1670 $forum_id = (int) bbp_get_forum_id( $forum_id );
1671 }
1672
1673 // Filter & return
1674 return (int) apply_filters( 'bbp_get_topic_forum_id', $forum_id, $topic_id );
1675 }
1676
1677 /**
1678 * Output the topics last active ID
1679 *
1680 * @since 2.0.0 bbPress (r2860)
1681 *
1682 * @param int $topic_id Optional. Forum id
1683 */
1684 function bbp_topic_last_active_id( $topic_id = 0 ) {
1685 echo bbp_get_topic_last_active_id( $topic_id );
1686 }
1687 /**
1688 * Return the topics last active ID
1689 *
1690 * @since 2.0.0 bbPress (r2860)
1691 *
1692 * @param int $topic_id Optional. Forum id
1693 * @return int Forum's last active id
1694 */
1695 function bbp_get_topic_last_active_id( $topic_id = 0 ) {
1696 $topic_id = bbp_get_topic_id( $topic_id );
1697 $active_id = (int) get_post_meta( $topic_id, '_bbp_last_active_id', true );
1698
1699 // Filter & return
1700 return (int) apply_filters( 'bbp_get_topic_last_active_id', $active_id, $topic_id );
1701 }
1702
1703 /**
1704 * Output the topics last update date/time (aka freshness)
1705 *
1706 * @since 2.0.0 bbPress (r2625)
1707 *
1708 * @param int $topic_id Optional. Topic id
1709 */
1710 function bbp_topic_last_active_time( $topic_id = 0 ) {
1711 echo bbp_get_topic_last_active_time( $topic_id );
1712 }
1713 /**
1714 * Return the topics last update date/time (aka freshness)
1715 *
1716 * @since 2.0.0 bbPress (r2625)
1717 *
1718 * @param int $topic_id Optional. Topic id
1719 * @return string Topic freshness
1720 */
1721 function bbp_get_topic_last_active_time( $topic_id = 0 ) {
1722 $topic_id = bbp_get_topic_id( $topic_id );
1723
1724 // Try to get the most accurate freshness time possible
1725 $last_active = get_post_meta( $topic_id, '_bbp_last_active_time', true );
1726 if ( empty( $last_active ) ) {
1727 $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1728 if ( ! empty( $reply_id ) ) {
1729 $last_active = get_post_field( 'post_date', $reply_id );
1730 } else {
1731 $last_active = get_post_field( 'post_date', $topic_id );
1732 }
1733 }
1734
1735 $last_active = ! empty( $last_active ) ? bbp_get_time_since( bbp_convert_date( $last_active ) ) : '';
1736
1737 // Filter & return
1738 return apply_filters( 'bbp_get_topic_last_active', $last_active, $topic_id );
1739 }
1740
1741 /** Topic Subscriptions *******************************************************/
1742
1743 /**
1744 * Output the topic subscription link
1745 *
1746 * @since 2.5.0 bbPress (r5156)
1747 * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1748 */
1749 function bbp_topic_subscription_link( $args = array() ) {
1750 echo bbp_get_topic_subscription_link( $args );
1751 }
1752
1753 /**
1754 * Get the topic subscription link
1755 *
1756 * A custom wrapper for bbp_get_user_subscribe_link()
1757 *
1758 * @since 2.5.0 bbPress (r5156)
1759 * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1760 */
1761 function bbp_get_topic_subscription_link( $args = array() ) {
1762
1763 // Defaults
1764 $retval = false;
1765 $user_id = bbp_get_current_user_id();
1766 $redirect_to = bbp_is_subscriptions()
1767 ? bbp_get_subscriptions_permalink( $user_id )
1768 : '';
1769
1770 // Parse the arguments
1771 $r = bbp_parse_args( $args, array(
1772 'user_id' => $user_id,
1773 'object_id' => bbp_get_topic_id(),
1774 'object_type' => 'post',
1775 'before' => '&nbsp;|&nbsp;',
1776 'after' => '',
1777 'subscribe' => esc_html__( 'Subscribe', 'bbpress' ),
1778 'unsubscribe' => esc_html__( 'Unsubscribe', 'bbpress' ),
1779 'redirect_to' => $redirect_to
1780 ), 'get_topic_subscribe_link' );
1781
1782 // Get the link
1783 $retval = bbp_get_user_subscribe_link( $r );
1784
1785 // Filter & return
1786 return apply_filters( 'bbp_get_topic_subscribe_link', $retval, $r, $args );
1787 }
1788
1789 /** Topic Favorites ***********************************************************/
1790
1791 /**
1792 * Output the topic favorite link
1793 *
1794 * @since 2.5.0 bbPress (r5156)
1795 * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1796 */
1797 function bbp_topic_favorite_link( $args = array() ) {
1798 echo bbp_get_topic_favorite_link( $args );
1799 }
1800
1801 /**
1802 * Get the forum favorite link
1803 *
1804 * A custom wrapper for bbp_get_user_favorites_link()
1805 *
1806 * @since 2.5.0 bbPress (r5156)
1807 * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1808 */
1809 function bbp_get_topic_favorite_link( $args = array() ) {
1810
1811 // No link
1812 $retval = false;
1813 $user_id = bbp_get_current_user_id();
1814 $redirect_to = bbp_is_favorites()
1815 ? bbp_get_favorites_permalink( $user_id )
1816 : '';
1817
1818 // Parse the arguments
1819 $r = bbp_parse_args( $args, array(
1820 'user_id' => $user_id,
1821 'object_id' => bbp_get_topic_id(),
1822 'object_type' => 'post',
1823 'before' => '',
1824 'after' => '',
1825 'favorite' => esc_html__( 'Favorite', 'bbpress' ),
1826 'favorited' => esc_html__( 'Unfavorite', 'bbpress' ),
1827 'redirect_to' => $redirect_to
1828 ), 'get_topic_favorite_link' );
1829
1830 // Get the link
1831 $retval = bbp_get_user_favorites_link( $r );
1832
1833 // Filter & return
1834 return apply_filters( 'bbp_get_topic_favorite_link', $retval, $r, $args );
1835 }
1836
1837 /** Topic Last Reply **********************************************************/
1838
1839 /**
1840 * Output the id of the topics last reply
1841 *
1842 * @since 2.0.0 bbPress (r2625)
1843 *
1844 * @param int $topic_id Optional. Topic id
1845 */
1846 function bbp_topic_last_reply_id( $topic_id = 0 ) {
1847 echo bbp_get_topic_last_reply_id( $topic_id );
1848 }
1849 /**
1850 * Return the id of the topics last reply
1851 *
1852 * @since 2.0.0 bbPress (r2625)
1853 *
1854 * @param int $topic_id Optional. Topic id
1855 * @return int Topic last reply id
1856 */
1857 function bbp_get_topic_last_reply_id( $topic_id = 0 ) {
1858 $topic_id = bbp_get_topic_id( $topic_id );
1859 $reply_id = (int) get_post_meta( $topic_id, '_bbp_last_reply_id', true );
1860
1861 // Filter & return
1862 return (int) apply_filters( 'bbp_get_topic_last_reply_id', $reply_id, $topic_id );
1863 }
1864
1865 /**
1866 * Output the title of the last reply inside a topic
1867 *
1868 * @since 2.0.0 bbPress (r2753)
1869 *
1870 * @param int $topic_id Optional. Topic id
1871 */
1872 function bbp_topic_last_reply_title( $topic_id = 0 ) {
1873 echo bbp_get_topic_last_reply_title( $topic_id );
1874 }
1875 /**
1876 * Return the title of the last reply inside a topic
1877 *
1878 * @since 2.0.0 bbPress (r2753)
1879 * @since 2.6.0 bbPress https://bbpress.trac.wordpress.org/ticket/3039
1880 *
1881 * @param int $topic_id Optional. Topic id
1882 * @return string Topic last reply title
1883 */
1884 function bbp_get_topic_last_reply_title( $topic_id = 0 ) {
1885 $topic_id = bbp_get_topic_id( $topic_id );
1886 $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1887 $retval = bbp_get_reply_title( $reply_id );
1888
1889 // Misspelled. Use 'bbp_get_topic_last_reply_title' hook instead.
1890 $retval = apply_filters( 'bbp_get_topic_last_topic_title', $retval, $topic_id, $reply_id );
1891
1892 // Filter & return
1893 return apply_filters( 'bbp_get_topic_last_reply_title', $retval, $topic_id, $reply_id );
1894 }
1895
1896 /**
1897 * Output the link to the last reply in a topic
1898 *
1899 * @since 2.0.0 bbPress (r2464)
1900 *
1901 * @param int $topic_id Optional. Topic id
1902 */
1903 function bbp_topic_last_reply_permalink( $topic_id = 0 ) {
1904 echo esc_url( bbp_get_topic_last_reply_permalink( $topic_id ) );
1905 }
1906 /**
1907 * Return the link to the last reply in a topic
1908 *
1909 * @since 2.0.0 bbPress (r2464)
1910 *
1911 * @param int $topic_id Optional. Topic id
1912 * @return string Permanent link to the reply
1913 */
1914 function bbp_get_topic_last_reply_permalink( $topic_id = 0 ) {
1915 $topic_id = bbp_get_topic_id( $topic_id );
1916 $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1917 $retval = bbp_get_reply_permalink( $reply_id );
1918
1919 // Filter & return
1920 return apply_filters( 'bbp_get_topic_last_reply_permalink', $retval, $topic_id, $reply_id );
1921 }
1922
1923 /**
1924 * Output the link to the last reply in a topic
1925 *
1926 * @since 2.0.0 bbPress (r2683)
1927 *
1928 * @param int $topic_id Optional. Topic id
1929 */
1930 function bbp_topic_last_reply_url( $topic_id = 0 ) {
1931 echo esc_url( bbp_get_topic_last_reply_url( $topic_id ) );
1932 }
1933 /**
1934 * Return the link to the last reply in a topic
1935 *
1936 * @since 2.0.0 bbPress (r2683)
1937 *
1938 * @param int $topic_id Optional. Topic id
1939 * @return string Topic last reply url
1940 */
1941 function bbp_get_topic_last_reply_url( $topic_id = 0 ) {
1942 $topic_id = bbp_get_topic_id( $topic_id );
1943 $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1944
1945 if ( ! empty( $reply_id ) && ( $reply_id !== $topic_id ) ) {
1946 $reply_url = bbp_get_reply_url( $reply_id );
1947 } else {
1948 $reply_url = bbp_get_topic_permalink( $topic_id );
1949 }
1950
1951 // Filter & return
1952 return apply_filters( 'bbp_get_topic_last_reply_url', $reply_url, $topic_id, $reply_id );
1953 }
1954
1955 /**
1956 * Output link to the most recent activity inside a topic, complete with link
1957 * attributes and content.
1958 *
1959 * @since 2.0.0 bbPress (r2625)
1960 *
1961 * @param int $topic_id Optional. Topic id
1962 */
1963 function bbp_topic_freshness_link( $topic_id = 0 ) {
1964 echo bbp_get_topic_freshness_link( $topic_id );
1965 }
1966 /**
1967 * Returns link to the most recent activity inside a topic, complete
1968 * with link attributes and content.
1969 *
1970 * @since 2.0.0 bbPress (r2625)
1971 *
1972 * @param int $topic_id Optional. Topic id
1973 * @return string Topic freshness link
1974 */
1975 function bbp_get_topic_freshness_link( $topic_id = 0 ) {
1976 $topic_id = bbp_get_topic_id( $topic_id );
1977 $link_url = bbp_get_topic_last_reply_url( $topic_id );
1978 $title = bbp_get_topic_last_reply_title( $topic_id );
1979 $time_since = bbp_get_topic_last_active_time( $topic_id );
1980
1981 if ( ! empty( $time_since ) ) {
1982 $anchor = '<a href="' . esc_url( $link_url ) . '" title="' . esc_attr( $title ) . '">' . esc_html( $time_since ) . '</a>';
1983 } else {
1984 $anchor = esc_html__( 'No Replies', 'bbpress' );
1985 }
1986
1987 // Filter & return
1988 return apply_filters( 'bbp_get_topic_freshness_link', $anchor, $topic_id, $time_since, $link_url, $title );
1989 }
1990
1991 /**
1992 * Output the replies link of the topic
1993 *
1994 * @since 2.0.0 bbPress (r2740)
1995 *
1996 * @param int $topic_id Optional. Topic id
1997 */
1998 function bbp_topic_replies_link( $topic_id = 0 ) {
1999 echo bbp_get_topic_replies_link( $topic_id );
2000 }
2001
2002 /**
2003 * Return the replies link of the topic
2004 *
2005 * @since 2.0.0 bbPress (r2740)
2006 *
2007 * @param int $topic_id Optional. Topic id
2008 */
2009 function bbp_get_topic_replies_link( $topic_id = 0 ) {
2010 $topic_id = bbp_get_topic_id( $topic_id );
2011 $link = bbp_get_topic_permalink( $topic_id );
2012 $replies = sprintf( _n( '%s reply', '%s replies', bbp_get_topic_reply_count( $topic_id, true ), 'bbpress' ), bbp_get_topic_reply_count( $topic_id, false ) );
2013
2014 // First link never has view=all
2015 $retval = bbp_get_view_all( 'edit_others_replies' )
2016 ? "<a href='" . esc_url( bbp_remove_view_all( $link ) ) . "'>" . esc_html( $replies ) . "</a>"
2017 : $replies;
2018
2019 // Any deleted replies?
2020 $deleted_int = bbp_get_topic_reply_count_hidden( $topic_id, true );
2021
2022 // This topic has hidden replies
2023 if ( ! empty( $deleted_int ) && current_user_can( 'edit_others_replies' ) ) {
2024
2025 // Hidden replies
2026 $deleted_num = bbp_get_topic_reply_count_hidden( $topic_id, false );
2027 $extra = ' ' . sprintf( _n( '(+%s hidden)', '(+%s hidden)', $deleted_int, 'bbpress' ), $deleted_num );
2028
2029 // Hidden link
2030 $retval .= ! bbp_get_view_all( 'edit_others_replies' )
2031 ? " <a href='" . esc_url( bbp_add_view_all( $link, true ) ) . "'>" . esc_html( $extra ) . "</a>"
2032 : " {$extra}";
2033 }
2034
2035 // Filter & return
2036 return apply_filters( 'bbp_get_topic_replies_link', $retval, $topic_id );
2037 }
2038
2039 /**
2040 * Output total reply count of a topic
2041 *
2042 * @since 2.0.0 bbPress (r2485)
2043 *
2044 * @param int $topic_id Optional. Topic id
2045 * @param boolean $integer Optional. Whether or not to format the result
2046 */
2047 function bbp_topic_reply_count( $topic_id = 0, $integer = false ) {
2048 echo bbp_get_topic_reply_count( $topic_id, $integer );
2049 }
2050 /**
2051 * Return total reply count of a topic
2052 *
2053 * @since 2.0.0 bbPress (r2485)
2054 *
2055 * @param int $topic_id Optional. Topic id
2056 * @param boolean $integer Optional. Whether or not to format the result
2057 * @return int Reply count
2058 */
2059 function bbp_get_topic_reply_count( $topic_id = 0, $integer = false ) {
2060 $topic_id = bbp_get_topic_id( $topic_id );
2061 $replies = (int) get_post_meta( $topic_id, '_bbp_reply_count', true );
2062 $filter = ( true === $integer )
2063 ? 'bbp_get_topic_reply_count_int'
2064 : 'bbp_get_topic_reply_count';
2065
2066 return apply_filters( $filter, $replies, $topic_id );
2067 }
2068
2069 /**
2070 * Output total post count of a topic
2071 *
2072 * @since 2.0.0 bbPress (r2954)
2073 *
2074 * @param int $topic_id Optional. Topic id
2075 * @param boolean $integer Optional. Whether or not to format the result
2076 */
2077 function bbp_topic_post_count( $topic_id = 0, $integer = false ) {
2078 echo bbp_get_topic_post_count( $topic_id, $integer );
2079 }
2080 /**
2081 * Return total post count of a topic
2082 *
2083 * @since 2.0.0 bbPress (r2954)
2084 *
2085 * @param int $topic_id Optional. Topic id
2086 * @param boolean $integer Optional. Whether or not to format the result
2087 * @return int Post count
2088 */
2089 function bbp_get_topic_post_count( $topic_id = 0, $integer = false ) {
2090 $topic_id = bbp_get_topic_id( $topic_id );
2091 $replies = ( (int) get_post_meta( $topic_id, '_bbp_reply_count', true ) ) + 1;
2092 $filter = ( true === $integer )
2093 ? 'bbp_get_topic_post_count_int'
2094 : 'bbp_get_topic_post_count';
2095
2096 return apply_filters( $filter, $replies, $topic_id );
2097 }
2098
2099 /**
2100 * Output total hidden reply count of a topic (hidden includes trashed and
2101 * spammed replies)
2102 *
2103 * @since 2.0.0 bbPress (r2740)
2104 *
2105 * @param int $topic_id Optional. Topic id
2106 * @param boolean $integer Optional. Whether or not to format the result
2107 */
2108 function bbp_topic_reply_count_hidden( $topic_id = 0, $integer = false ) {
2109 echo bbp_get_topic_reply_count_hidden( $topic_id, $integer );
2110 }
2111 /**
2112 * Return total hidden reply count of a topic (hidden includes trashed
2113 * and spammed replies)
2114 *
2115 * @since 2.0.0 bbPress (r2740)
2116 *
2117 * @param int $topic_id Optional. Topic id
2118 * @param boolean $integer Optional. Whether or not to format the result
2119 * @return int Topic hidden reply count
2120 */
2121 function bbp_get_topic_reply_count_hidden( $topic_id = 0, $integer = false ) {
2122 $topic_id = bbp_get_topic_id( $topic_id );
2123 $replies = (int) get_post_meta( $topic_id, '_bbp_reply_count_hidden', true );
2124 $filter = ( true === $integer )
2125 ? 'bbp_get_topic_reply_count_hidden_int'
2126 : 'bbp_get_topic_reply_count_hidden';
2127
2128 return apply_filters( $filter, $replies, $topic_id );
2129 }
2130
2131 /**
2132 * Output total voice count of a topic
2133 *
2134 * @since 2.0.0 bbPress (r2567)
2135 *
2136 * @param int $topic_id Optional. Topic id
2137 */
2138 function bbp_topic_voice_count( $topic_id = 0, $integer = false ) {
2139 echo bbp_get_topic_voice_count( $topic_id, $integer );
2140 }
2141 /**
2142 * Return total voice count of a topic
2143 *
2144 * @since 2.0.0 bbPress (r2567)
2145 *
2146 * @param int $topic_id Optional. Topic id
2147 * @return int Voice count of the topic
2148 */
2149 function bbp_get_topic_voice_count( $topic_id = 0, $integer = false ) {
2150 $topic_id = bbp_get_topic_id( $topic_id );
2151 $voices = (int) get_post_meta( $topic_id, '_bbp_voice_count', true );
2152 $filter = ( true === $integer )
2153 ? 'bbp_get_topic_voice_count_int'
2154 : 'bbp_get_topic_voice_count';
2155
2156 return apply_filters( $filter, $voices, $topic_id );
2157 }
2158
2159 /**
2160 * Output a the tags of a topic
2161 *
2162 * @since 2.0.0 bbPress (r2688)
2163 *
2164 * @param int $topic_id Optional. Topic id
2165 * @param array $args See {@link bbp_get_topic_tag_list()}
2166 */
2167 function bbp_topic_tag_list( $topic_id = 0, $args = array() ) {
2168 echo bbp_get_topic_tag_list( $topic_id, $args );
2169 }
2170 /**
2171 * Return the tags of a topic
2172 *
2173 * @since 2.0.0 bbPress (r2688)
2174 *
2175 * @param int $topic_id Optional. Topic id
2176 * @param array $args This function supports these arguments:
2177 * - before: Before the tag list
2178 * - sep: Tag separator
2179 * - after: After the tag list
2180 * @return string Tag list of the topic
2181 */
2182 function bbp_get_topic_tag_list( $topic_id = 0, $args = array() ) {
2183
2184 // Bail if topic-tags are off
2185 if ( ! bbp_allow_topic_tags() ) {
2186 return '';
2187 }
2188
2189 // Parse arguments against default values
2190 $r = bbp_parse_args( $args, array(
2191 'before' => '<div class="bbp-topic-tags"><p>' . esc_html__( 'Tagged:', 'bbpress' ) . '&nbsp;',
2192 'sep' => ', ',
2193 'after' => '</p></div>',
2194 'none' => ''
2195 ), 'get_topic_tag_list' );
2196
2197 $topic_id = bbp_get_topic_id( $topic_id );
2198
2199 // Topic is spammed, so display pre-spam terms
2200 if ( bbp_is_topic_spam( $topic_id ) ) {
2201
2202 // Get pre-spam terms
2203 $terms = get_post_meta( $topic_id, '_bbp_spam_topic_tags', true );
2204
2205 // If terms exist, implode them and compile the return value
2206 if ( ! empty( $terms ) ) {
2207 $terms = $r['before'] . implode( $r['sep'], $terms ) . $r['after'];
2208 }
2209
2210 // Topic is not spam so display a clickable term list
2211 } else {
2212 $terms = get_the_term_list( $topic_id, bbp_get_topic_tag_tax_id(), $r['before'], $r['sep'], $r['after'] );
2213 }
2214
2215 // No terms so return none string
2216 if ( ! empty( $terms ) ) {
2217 $retval = $terms;
2218 } else {
2219 $retval = $r['none'];
2220 }
2221
2222 return $retval;
2223 }
2224
2225 /**
2226 * Output the row class of a topic
2227 *
2228 * @since 2.0.0 bbPress (r2667)
2229 *
2230 * @param int $topic_id Optional. Topic id
2231 * @param array Extra classes you can pass when calling this function
2232 */
2233 function bbp_topic_class( $topic_id = 0, $classes = array() ) {
2234 echo bbp_get_topic_class( $topic_id, $classes );
2235 }
2236 /**
2237 * Return the row class of a topic
2238 *
2239 * @since 2.0.0 bbPress (r2667)
2240 *
2241 * @param int $topic_id Optional. Topic id
2242 * @param array Extra classes you can pass when calling this function
2243 * @return string Row class of a topic
2244 */
2245 function bbp_get_topic_class( $topic_id = 0, $classes = array() ) {
2246 $bbp = bbpress();
2247 $topic_id = bbp_get_topic_id( $topic_id );
2248 $forum_id = bbp_get_topic_forum_id( $topic_id );
2249 $author_id = bbp_get_topic_author_id( $topic_id );
2250 $classes = array_filter( (array) $classes );
2251 $count = isset( $bbp->topic_query->current_post )
2252 ? (int) $bbp->topic_query->current_post
2253 : 1;
2254
2255 // Stripes
2256 $even_odd = ( $count % 2 )
2257 ? 'even'
2258 : 'odd';
2259
2260 // Forum moderator replied to topic
2261 $forum_moderator = ( bbp_is_user_forum_moderator( $author_id, $forum_id ) === $author_id )
2262 ? 'forum-mod'
2263 : '';
2264
2265 // Is this topic a sticky?
2266 $sticky = bbp_is_topic_sticky( $topic_id, false )
2267 ? 'sticky'
2268 : '';
2269
2270 // Is this topic a super-sticky?
2271 $super_sticky = bbp_is_topic_super_sticky( $topic_id )
2272 ? 'super-sticky'
2273 : '';
2274
2275 // Get topic classes
2276 $topic_classes = array(
2277 'loop-item-' . $count,
2278 'user-id-' . $author_id,
2279 'bbp-parent-forum-' . $forum_id,
2280 $even_odd,
2281 $forum_moderator,
2282 $sticky,
2283 $super_sticky
2284 );
2285
2286 // Run the topic classes through the post-class filters, which also
2287 // handles the escaping of each individual class.
2288 $post_classes = get_post_class( array_merge( $classes, $topic_classes ), $topic_id );
2289
2290 // Filter
2291 $new_classes = apply_filters( 'bbp_get_topic_class', $post_classes, $topic_id, $classes );
2292
2293 // Return
2294 return 'class="' . implode( ' ', $new_classes ) . '"';
2295 }
2296
2297 /** Topic Admin Links *********************************************************/
2298
2299 /**
2300 * Output admin links for topic
2301 *
2302 * @param array $args See {@link bbp_get_topic_admin_links()}
2303 */
2304 function bbp_topic_admin_links( $args = array() ) {
2305 echo bbp_get_topic_admin_links( $args );
2306 }
2307 /**
2308 * Return admin links for topic.
2309 *
2310 * Move topic functionality is handled by the edit topic page.
2311 *
2312 * @param array $args This function supports these arguments:
2313 * - id: Optional. Topic id
2314 * - before: Before the links
2315 * - after: After the links
2316 * - sep: Links separator
2317 * - links: Topic admin links array
2318 * @return string Topic admin links
2319 */
2320 function bbp_get_topic_admin_links( $args = array() ) {
2321
2322 // Parse arguments against default values
2323 $r = bbp_parse_args( $args, array(
2324 'id' => bbp_get_topic_id(),
2325 'before' => '<span class="bbp-admin-links">',
2326 'after' => '</span>',
2327 'sep' => ' | ',
2328 'links' => array()
2329 ), 'get_topic_admin_links' );
2330
2331 if ( empty( $r['links'] ) ) {
2332 $r['links'] = apply_filters( 'bbp_topic_admin_links', array(
2333 'edit' => bbp_get_topic_edit_link ( $r ),
2334 'merge' => bbp_get_topic_merge_link ( $r ),
2335 'close' => bbp_get_topic_close_link ( $r ),
2336 'stick' => bbp_get_topic_stick_link ( $r ),
2337 'trash' => bbp_get_topic_trash_link ( $r ),
2338 'spam' => bbp_get_topic_spam_link ( $r ),
2339 'approve' => bbp_get_topic_approve_link( $r ),
2340 'reply' => bbp_get_topic_reply_link ( $r )
2341 ), $r['id'] );
2342 }
2343
2344 // See if links need to be unset
2345 $topic_status = bbp_get_topic_status( $r['id'] );
2346 if ( in_array( $topic_status, bbp_get_non_public_topic_statuses(), true ) ) {
2347
2348 // Close link shouldn't be visible on trashed/spammed/pending topics
2349 unset( $r['links']['close'] );
2350
2351 // Spam link shouldn't be visible on trashed topics
2352 if ( bbp_get_trash_status_id() === $topic_status ) {
2353 unset( $r['links']['spam'] );
2354
2355 // Trash link shouldn't be visible on spam topics
2356 } elseif ( bbp_get_spam_status_id() === $topic_status ) {
2357 unset( $r['links']['trash'] );
2358 }
2359 }
2360
2361 // Process the admin links
2362 $links = implode( $r['sep'], array_filter( $r['links'] ) );
2363 $retval = $r['before'] . $links . $r['after'];
2364
2365 // Filter & return
2366 return apply_filters( 'bbp_get_topic_admin_links', $retval, $r, $args );
2367 }
2368
2369 /**
2370 * Output the edit link of the topic
2371 *
2372 * @since 2.0.0 bbPress (r2727)
2373 *
2374 * @param array $args See {@link bbp_get_topic_edit_link()}
2375 */
2376 function bbp_topic_edit_link( $args = array() ) {
2377 echo bbp_get_topic_edit_link( $args );
2378 }
2379
2380 /**
2381 * Return the edit link of the topic
2382 *
2383 * @since 2.0.0 bbPress (r2727)
2384 *
2385 * @param array $args This function supports these args:
2386 * - id: Optional. Topic id
2387 * - link_before: Before the link
2388 * - link_after: After the link
2389 * - edit_text: Edit text
2390 * @return string Topic edit link
2391 */
2392 function bbp_get_topic_edit_link( $args = array() ) {
2393
2394 // Parse arguments against default values
2395 $r = bbp_parse_args( $args, array(
2396 'id' => 0,
2397 'link_before' => '',
2398 'link_after' => '',
2399 'edit_text' => esc_html__( 'Edit', 'bbpress' )
2400 ), 'get_topic_edit_link' );
2401
2402 // Get the topic
2403 $topic = bbp_get_topic( $r['id'] );
2404
2405 // Bypass check if user has caps
2406 if ( ! current_user_can( 'edit_others_topics' ) ) {
2407
2408 // User cannot edit or it is past the lock time
2409 if ( empty( $topic ) || ! current_user_can( 'edit_topic', $topic->ID ) || bbp_past_edit_lock( $topic->post_date_gmt ) ) {
2410 return;
2411 }
2412 }
2413
2414 // Get uri
2415 $uri = bbp_get_topic_edit_url( $topic->ID );
2416
2417 // Bail if no uri
2418 if ( empty( $uri ) ) {
2419 return;
2420 }
2421
2422 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-edit-link">' . $r['edit_text'] . '</a>' . $r['link_after'];
2423
2424 // Filter & return
2425 return apply_filters( 'bbp_get_topic_edit_link', $retval, $r, $args );
2426 }
2427
2428 /**
2429 * Output URL to the topic edit page
2430 *
2431 * @since 2.0.0 bbPress (r2753)
2432 *
2433 * @param int $topic_id Optional. Topic id
2434 */
2435 function bbp_topic_edit_url( $topic_id = 0 ) {
2436 echo esc_url( bbp_get_topic_edit_url( $topic_id ) );
2437 }
2438 /**
2439 * Return URL to the topic edit page
2440 *
2441 * @since 2.0.0 bbPress (r2753)
2442 *
2443 * @param int $topic_id Optional. Topic id
2444 * @return string Topic edit url
2445 */
2446 function bbp_get_topic_edit_url( $topic_id = 0 ) {
2447
2448 $topic = bbp_get_topic( $topic_id );
2449 if ( empty( $topic ) ) {
2450 return;
2451 }
2452
2453 // Remove view=all link from edit
2454 $topic_link = bbp_remove_view_all( bbp_get_topic_permalink( $topic_id ) );
2455
2456 // Pretty permalinks, previously used `bbp_use_pretty_urls()`
2457 // https://bbpress.trac.wordpress.org/ticket/3054
2458 if ( false === strpos( $topic_link, '?' ) ) {
2459 $url = trailingslashit( $topic_link ) . bbp_get_edit_slug();
2460 $url = user_trailingslashit( $url );
2461
2462 // Unpretty permalinks
2463 } else {
2464 $url = add_query_arg( array(
2465 bbp_get_topic_post_type() => $topic->post_name,
2466 bbp_get_edit_rewrite_id() => '1'
2467 ), $topic_link );
2468 }
2469
2470 // Maybe add view=all
2471 $url = bbp_add_view_all( $url );
2472
2473 // Filter & return
2474 return apply_filters( 'bbp_get_topic_edit_url', $url, $topic_id );
2475 }
2476
2477 /**
2478 * Output the trash link of the topic
2479 *
2480 * @since 2.0.0 bbPress (r2727)
2481 *
2482 * @param array $args See {@link bbp_get_topic_trash_link()}
2483 */
2484 function bbp_topic_trash_link( $args = array() ) {
2485 echo bbp_get_topic_trash_link( $args );
2486 }
2487
2488 /**
2489 * Return the trash link of the topic
2490 *
2491 * @since 2.0.0 bbPress (r2727)
2492 *
2493 * @param array $args This function supports these args:
2494 * - id: Optional. Topic id
2495 * - link_before: Before the link
2496 * - link_after: After the link
2497 * - sep: Links separator
2498 * - trash_text: Trash text
2499 * - restore_text: Restore text
2500 * - delete_text: Delete text
2501 * @return string Topic trash link
2502 */
2503 function bbp_get_topic_trash_link( $args = array() ) {
2504
2505 // Parse arguments against default values
2506 $r = bbp_parse_args( $args, array(
2507 'id' => 0,
2508 'link_before' => '',
2509 'link_after' => '',
2510 'sep' => ' | ',
2511 'trash_text' => esc_html__( 'Trash', 'bbpress' ),
2512 'restore_text' => esc_html__( 'Restore', 'bbpress' ),
2513 'delete_text' => esc_html__( 'Delete', 'bbpress' )
2514 ), 'get_topic_trash_link' );
2515
2516 // Get topic
2517 $topic = bbp_get_topic( $r['id'] );
2518
2519 // Bail if no topic or current user cannot delete
2520 if ( empty( $topic ) || ! current_user_can( 'delete_topic', $topic->ID ) ) {
2521 return;
2522 }
2523
2524 $actions = array();
2525 $trash_days = bbp_get_trash_days( bbp_get_topic_post_type() );
2526
2527 if ( bbp_is_topic_trash( $topic->ID ) ) {
2528 $actions['untrash'] = '<a title="' . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_topic_trash', 'sub_action' => 'untrash', 'topic_id' => $topic->ID ) ), 'untrash-' . $topic->post_type . '_' . $topic->ID ) ) . '" class="bbp-topic-restore-link">' . $r['restore_text'] . '</a>';
2529 } elseif ( ! empty( $trash_days ) ) {
2530 $actions['trash'] = '<a title="' . esc_attr__( 'Move this item to the Trash', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_topic_trash', 'sub_action' => 'trash', 'topic_id' => $topic->ID ) ), 'trash-' . $topic->post_type . '_' . $topic->ID ) ) . '" class="bbp-topic-trash-link">' . $r['trash_text'] . '</a>';
2531 }
2532
2533 if ( bbp_is_topic_trash( $topic->ID ) || empty( $trash_days ) ) {
2534 $actions['delete'] = '<a title="' . esc_attr__( 'Delete this item permanently', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_topic_trash', 'sub_action' => 'delete', 'topic_id' => $topic->ID ) ), 'delete-' . $topic->post_type . '_' . $topic->ID ) ) . '" onclick="return confirm(\'' . esc_js( esc_html__( 'Are you sure you want to delete that permanently?', 'bbpress' ) ) . '\' );" class="bbp-topic-delete-link">' . $r['delete_text'] . '</a>';
2535 }
2536
2537 // Process the admin links
2538 $retval = $r['link_before'] . implode( $r['sep'], $actions ) . $r['link_after'];
2539
2540 // Filter & return
2541 return apply_filters( 'bbp_get_topic_trash_link', $retval, $r, $args );
2542 }
2543
2544 /**
2545 * Output the close link of the topic
2546 *
2547 * @since 2.0.0 bbPress (r2727)
2548 *
2549 * @param array $args See {@link bbp_get_topic_close_link()}
2550 */
2551 function bbp_topic_close_link( $args = array() ) {
2552 echo bbp_get_topic_close_link( $args );
2553 }
2554
2555 /**
2556 * Return the close link of the topic
2557 *
2558 * @since 2.0.0 bbPress (r2727)
2559 *
2560 * @param array $args This function supports these args:
2561 * - id: Optional. Topic id
2562 * - link_before: Before the link
2563 * - link_after: After the link
2564 * - close_text: Close text
2565 * - open_text: Open text
2566 * @return string Topic close link
2567 */
2568 function bbp_get_topic_close_link( $args = array() ) {
2569
2570 // Parse arguments against default values
2571 $r = bbp_parse_args( $args, array(
2572 'id' => 0,
2573 'link_before' => '',
2574 'link_after' => '',
2575 'sep' => ' | ',
2576 'close_text' => esc_html_x( 'Close', 'Close the topic', 'bbpress' ),
2577 'open_text' => esc_html_x( 'Open', 'Open the topic', 'bbpress' )
2578 ), 'get_topic_close_link' );
2579
2580 // Get topic
2581 $topic = bbp_get_topic( $r['id'] );
2582
2583 // Bail if no topic or current user cannot moderate
2584 if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2585 return;
2586 }
2587
2588 $display = bbp_is_topic_open( $topic->ID ) ? $r['close_text'] : $r['open_text'];
2589 $uri = add_query_arg( array( 'action' => 'bbp_toggle_topic_close', 'topic_id' => $topic->ID ) );
2590 $uri = wp_nonce_url( $uri, 'close-topic_' . $topic->ID );
2591 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-close-link">' . $display . '</a>' . $r['link_after'];
2592
2593 // Filter & return
2594 return apply_filters( 'bbp_get_topic_close_link', $retval, $r, $args );
2595 }
2596
2597 /**
2598 * Output the approve link of the topic
2599 *
2600 * @since 2.6.0 bbPress (r5504)
2601 *
2602 * @param array $args See {@link bbp_get_topic_approve_link()}
2603 */
2604 function bbp_topic_approve_link( $args = array() ) {
2605 echo bbp_get_topic_approve_link( $args );
2606 }
2607
2608 /**
2609 * Return the approve link of the topic
2610 *
2611 * @since 2.6.0 bbPress (r5504)
2612 *
2613 * @param array $args This function supports these args:
2614 * - id: Optional. Topic id
2615 * - link_before: Before the link
2616 * - link_after: After the link
2617 * - sep: Separator between links
2618 * - approve_text: Approve text
2619 * - unapprove_text: Unapprove text
2620 * @return string Topic approve link
2621 */
2622 function bbp_get_topic_approve_link( $args = array() ) {
2623
2624 // Parse arguments against default values
2625 $r = bbp_parse_args( $args, array(
2626 'id' => 0,
2627 'link_before' => '',
2628 'link_after' => '',
2629 'sep' => ' | ',
2630 'approve_text' => esc_html_x( 'Approve', 'Approve the topic', 'bbpress' ),
2631 'unapprove_text' => esc_html_x( 'Unapprove', 'Unapprove the topic', 'bbpress' )
2632 ), 'get_topic_approve_link' );
2633
2634 // Get topic
2635 $topic = bbp_get_topic( $r['id'] );
2636
2637 // Bail if no topic or current user cannot moderate
2638 if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2639 return;
2640 }
2641
2642 $display = bbp_is_topic_pending( $topic->ID ) ? $r['approve_text'] : $r['unapprove_text'];
2643 $uri = add_query_arg( array( 'action' => 'bbp_toggle_topic_approve', 'topic_id' => $topic->ID ) );
2644 $uri = wp_nonce_url( $uri, 'approve-topic_' . $topic->ID );
2645 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-approve-link">' . $display . '</a>' . $r['link_after'];
2646
2647 // Filter & return
2648 return apply_filters( 'bbp_get_topic_approve_link', $retval, $r, $args );
2649 }
2650
2651 /**
2652 * Output the stick link of the topic
2653 *
2654 * @since 2.0.0 bbPress (r2754)
2655 *
2656 * @param array $args See {@link bbp_get_topic_stick_link()}
2657 */
2658 function bbp_topic_stick_link( $args = array() ) {
2659 echo bbp_get_topic_stick_link( $args );
2660 }
2661
2662 /**
2663 * Return the stick link of the topic
2664 *
2665 * @since 2.0.0 bbPress (r2754)
2666 *
2667 * @param array $args This function supports these args:
2668 * - id: Optional. Topic id
2669 * - link_before: Before the link
2670 * - link_after: After the link
2671 * - stick_text: Stick text
2672 * - unstick_text: Unstick text
2673 * - super_text: Stick to front text
2674 *
2675 * @return string Topic stick link
2676 */
2677 function bbp_get_topic_stick_link( $args = array() ) {
2678
2679 // Parse arguments against default values
2680 $r = bbp_parse_args( $args, array(
2681 'id' => 0,
2682 'link_before' => '',
2683 'link_after' => '',
2684 'stick_text' => esc_html__( 'Stick', 'bbpress' ),
2685 'unstick_text' => esc_html__( 'Unstick', 'bbpress' ),
2686 'super_text' => esc_html__( '(to front)', 'bbpress' ),
2687 ), 'get_topic_stick_link' );
2688
2689 // Get topic
2690 $topic = bbp_get_topic( $r['id'] );
2691
2692 // Bail if no topic or current user cannot moderate
2693 if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2694 return;
2695 }
2696
2697 $is_sticky = bbp_is_topic_sticky( $topic->ID );
2698
2699 $stick_uri = add_query_arg( array( 'action' => 'bbp_toggle_topic_stick', 'topic_id' => $topic->ID ) );
2700 $stick_uri = wp_nonce_url( $stick_uri, 'stick-topic_' . $topic->ID );
2701
2702 $stick_display = ( true === $is_sticky ) ? $r['unstick_text'] : $r['stick_text'];
2703 $stick_display = '<a href="' . esc_url( $stick_uri ) . '" class="bbp-topic-sticky-link">' . $stick_display . '</a>';
2704
2705 if ( empty( $is_sticky ) ) {
2706 $super_uri = add_query_arg( array( 'action' => 'bbp_toggle_topic_stick', 'topic_id' => $topic->ID, 'super' => 1 ) );
2707 $super_uri = wp_nonce_url( $super_uri, 'stick-topic_' . $topic->ID );
2708
2709 $super_display = ' <a href="' . esc_url( $super_uri ) . '" class="bbp-topic-super-sticky-link">' . $r['super_text'] . '</a>';
2710 } else {
2711 $super_display = '';
2712 }
2713
2714 // Combine the HTML into 1 string
2715 $retval = $r['link_before'] . $stick_display . $super_display . $r['link_after'];
2716
2717 // Filter & return
2718 return apply_filters( 'bbp_get_topic_stick_link', $retval, $r, $args );
2719 }
2720
2721 /**
2722 * Output the merge link of the topic
2723 *
2724 * @since 2.0.0 bbPress (r2756)
2725 *
2726 * @param array $args
2727 */
2728 function bbp_topic_merge_link( $args = array() ) {
2729 echo bbp_get_topic_merge_link( $args );
2730 }
2731
2732 /**
2733 * Return the merge link of the topic
2734 *
2735 * @since 2.0.0 bbPress (r2756)
2736 *
2737 * @param array $args This function supports these args:
2738 * - id: Optional. Topic id
2739 * - link_before: Before the link
2740 * - link_after: After the link
2741 * - merge_text: Merge text
2742 *
2743 * @return string Topic merge link
2744 */
2745 function bbp_get_topic_merge_link( $args = array() ) {
2746
2747 // Parse arguments against default values
2748 $r = bbp_parse_args( $args, array(
2749 'id' => 0,
2750 'link_before' => '',
2751 'link_after' => '',
2752 'merge_text' => esc_html__( 'Merge', 'bbpress' ),
2753 ), 'get_topic_merge_link' );
2754
2755 // Get topic
2756 $topic = bbp_get_topic( $r['id'] );
2757
2758 // Bail if no topic or current user cannot moderate
2759 if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2760 return;
2761 }
2762
2763 $uri = add_query_arg( array( 'action' => 'merge' ), bbp_get_topic_edit_url( $topic->ID ) );
2764 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-merge-link">' . $r['merge_text'] . '</a>' . $r['link_after'];
2765
2766 // Filter & return
2767 return apply_filters( 'bbp_get_topic_merge_link', $retval, $r, $args );
2768 }
2769
2770 /**
2771 * Output the spam link of the topic
2772 *
2773 * @since 2.0.0 bbPress (r2727)
2774 *
2775 * @param array $args See {@link bbp_get_topic_spam_link()}
2776 */
2777 function bbp_topic_spam_link( $args = array() ) {
2778 echo bbp_get_topic_spam_link( $args );
2779 }
2780
2781 /**
2782 * Return the spam link of the topic
2783 *
2784 * @since 2.0.0 bbPress (r2727)
2785 *
2786 * @param array $args This function supports these args:
2787 * - id: Optional. Topic id
2788 * - link_before: Before the link
2789 * - link_after: After the link
2790 * - spam_text: Spam text
2791 * - unspam_text: Unspam text
2792 *
2793 * @return string Topic spam link
2794 */
2795 function bbp_get_topic_spam_link( $args = array() ) {
2796
2797 // Parse arguments against default values
2798 $r = bbp_parse_args( $args, array(
2799 'id' => 0,
2800 'link_before' => '',
2801 'link_after' => '',
2802 'sep' => ' | ',
2803 'spam_text' => esc_html__( 'Spam', 'bbpress' ),
2804 'unspam_text' => esc_html__( 'Unspam', 'bbpress' )
2805 ), 'get_topic_spam_link' );
2806
2807 $topic = bbp_get_topic( $r['id'] );
2808
2809 if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2810 return;
2811 }
2812
2813 $display = bbp_is_topic_spam( $topic->ID ) ? $r['unspam_text'] : $r['spam_text'];
2814 $uri = add_query_arg( array( 'action' => 'bbp_toggle_topic_spam', 'topic_id' => $topic->ID ) );
2815 $uri = wp_nonce_url( $uri, 'spam-topic_' . $topic->ID );
2816 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-spam-link">' . $display . '</a>' . $r['link_after'];
2817
2818 // Filter & return
2819 return apply_filters( 'bbp_get_topic_spam_link', $retval, $r, $args );
2820 }
2821
2822 /**
2823 * Output the link to go directly to the reply form
2824 *
2825 * @since 2.4.0 bbPress (r4966)
2826 *
2827 * @param array $args
2828 */
2829 function bbp_topic_reply_link( $args = array() ) {
2830 echo bbp_get_topic_reply_link( $args );
2831 }
2832
2833 /**
2834 * Return the link to go directly to the reply form
2835 *
2836 * @since 2.4.0 bbPress (r4966)
2837 *
2838 * @param array $args Arguments
2839 *
2840 * @return string Link for a reply to a topic
2841 */
2842 function bbp_get_topic_reply_link( $args = array() ) {
2843
2844 // Parse arguments against default values
2845 $r = bbp_parse_args( $args, array(
2846 'id' => 0,
2847 'link_before' => '',
2848 'link_after' => '',
2849 'reply_text' => esc_html_x( 'Reply', 'verb', 'bbpress' ),
2850 'add_below' => 'post',
2851 'respond_id' => 'new-reply-' . bbp_get_topic_id(),
2852 ), 'get_topic_reply_link' );
2853
2854 // Get the topic to use it's ID and post_parent
2855 $topic = bbp_get_topic( $r['id'] );
2856
2857 // Bail if no topic or user cannot reply
2858 if ( empty( $topic ) || bbp_is_single_reply() || ! bbp_current_user_can_access_create_reply_form() ) {
2859 return;
2860 }
2861
2862 // Only add onclick if replies are threaded
2863 $onclick = bbp_thread_replies()
2864 ? ' onclick="return addReply.cancelForm();"'
2865 : '';
2866
2867 // Add $uri to the array, to be passed through the filter
2868 $r['uri'] = remove_query_arg( array( 'bbp_reply_to', '_wpnonce' ) ) . '#new-post';
2869 $retval = $r['link_before'] . '<a role="button" href="' . esc_url( $r['uri'] ) . '" class="bbp-topic-reply-link"' . $onclick . '>' . $r['reply_text'] . '</a>' . $r['link_after'];
2870
2871 // Filter & return
2872 return apply_filters( 'bbp_get_topic_reply_link', $retval, $r, $args );
2873 }
2874
2875 /** Topic Pagination **********************************************************/
2876
2877 /**
2878 * Return the base URL used inside of pagination links
2879 *
2880 * @since 2.6.0 bbPress (r6402)
2881 *
2882 * @param int $forum_id
2883 * @return string
2884 */
2885 function bbp_get_topics_pagination_base( $forum_id = 0 ) {
2886
2887 // If pretty permalinks are enabled, make our pagination pretty
2888 if ( bbp_use_pretty_urls() ) {
2889
2890 // User's topics
2891 if ( bbp_is_single_user_topics() ) {
2892 $base = bbp_get_user_topics_created_url( bbp_get_displayed_user_id() );
2893
2894 // User's engagements
2895 } elseif ( bbp_is_single_user_engagements() ) {
2896 $base = bbp_get_user_engagements_url( bbp_get_displayed_user_id() );
2897
2898 // User's favorites
2899 } elseif ( bbp_is_favorites() ) {
2900 $base = bbp_get_favorites_permalink( bbp_get_displayed_user_id() );
2901
2902 // User's subscriptions
2903 } elseif ( bbp_is_subscriptions() ) {
2904 $base = bbp_get_subscriptions_permalink( bbp_get_displayed_user_id() );
2905
2906 // Root profile page
2907 } elseif ( bbp_is_single_user() ) {
2908 $base = bbp_get_user_profile_url( bbp_get_displayed_user_id() );
2909
2910 // Any single post (for shortcodes, ahead of shortcodeables below)
2911 } elseif ( is_singular() ) {
2912 $base = get_permalink();
2913
2914 // View
2915 } elseif ( bbp_is_single_view() ) {
2916 $base = bbp_get_view_url();
2917
2918 // Topic tag
2919 } elseif ( bbp_is_topic_tag() ) {
2920 $base = bbp_get_topic_tag_link();
2921
2922 // Forum archive
2923 } elseif ( bbp_is_forum_archive() ) {
2924 $base = bbp_get_forums_url();
2925
2926 // Topic archive
2927 } elseif ( bbp_is_topic_archive() ) {
2928 $base = bbp_get_topics_url();
2929
2930 // Default
2931 } else {
2932 $base = get_permalink( $forum_id );
2933 }
2934
2935 // Use pagination base
2936 $base = trailingslashit( $base ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' );
2937
2938 // Unpretty pagination
2939 } else {
2940 $base = add_query_arg( 'paged', '%#%' );
2941 }
2942
2943 // Filter & return
2944 return apply_filters( 'bbp_get_topics_pagination_base', $base, $forum_id );
2945 }
2946
2947 /**
2948 * Output the pagination count
2949 *
2950 * The results are unescaped by design, to allow them to be filtered freely via
2951 * the 'bbp_get_forum_pagination_count' filter.
2952 *
2953 * @since 2.0.0 bbPress (r2519)
2954 */
2955 function bbp_forum_pagination_count() {
2956 echo bbp_get_forum_pagination_count();
2957 }
2958 /**
2959 * Return the pagination count
2960 *
2961 * @since 2.0.0 bbPress (r2519)
2962 *
2963 * @return string Forum Pagination count
2964 */
2965 function bbp_get_forum_pagination_count() {
2966 $bbp = bbpress();
2967
2968 // Define local variable(s)
2969 $retstr = '';
2970
2971 // Topic query exists
2972 if ( ! empty( $bbp->topic_query ) ) {
2973
2974 // Set pagination values
2975 $count_int = intval( $bbp->topic_query->post_count );
2976 $start_num = intval( ( $bbp->topic_query->paged - 1 ) * $bbp->topic_query->posts_per_page ) + 1;
2977 $total_int = ! empty( $bbp->topic_query->found_posts )
2978 ? (int) $bbp->topic_query->found_posts
2979 : $count_int;
2980
2981 // Format numbers for display
2982 $count_num = bbp_number_format( $count_int );
2983 $from_num = bbp_number_format( $start_num );
2984 $total = bbp_number_format( $total_int );
2985 $to_num = bbp_number_format( ( $start_num + ( $bbp->topic_query->posts_per_page - 1 ) > $bbp->topic_query->found_posts )
2986 ? $bbp->topic_query->found_posts
2987 : $start_num + ( $bbp->topic_query->posts_per_page - 1 ) );
2988
2989 // Several topics in a forum with a single page
2990 if ( empty( $to_num ) ) {
2991 $retstr = sprintf( _n( 'Viewing %1$s topic', 'Viewing %1$s topics', $total_int, 'bbpress' ), $total );
2992
2993 // Several topics in a forum with several pages
2994 } else {
2995 $retstr = sprintf( _n( 'Viewing topic %2$s (of %4$s total)', 'Viewing %1$s topics - %2$s through %3$s (of %4$s total)', $total_int, 'bbpress' ), $count_num, $from_num, $to_num, $total );
2996 }
2997
2998 // Escape results of _n()
2999 $retstr = esc_html( $retstr );
3000 }
3001
3002 // Filter & return
3003 return apply_filters( 'bbp_get_forum_pagination_count', $retstr );
3004 }
3005
3006 /**
3007 * Output pagination links
3008 *
3009 * @since 2.0.0 bbPress (r2519)
3010 */
3011 function bbp_forum_pagination_links() {
3012 echo bbp_get_forum_pagination_links();
3013 }
3014 /**
3015 * Return pagination links
3016 *
3017 * @since 2.0.0 bbPress (r2519)
3018 *
3019 * @return string Pagination links
3020 */
3021 function bbp_get_forum_pagination_links() {
3022 $bbp = bbpress();
3023
3024 if ( empty( $bbp->topic_query ) ) {
3025 return false;
3026 }
3027
3028 // Filter & return
3029 return apply_filters( 'bbp_get_forum_pagination_links', $bbp->topic_query->pagination_links );
3030 }
3031
3032 /**
3033 * Displays topic notices
3034 *
3035 * @since 2.0.0 bbPress (r2744)
3036 */
3037 function bbp_topic_notices() {
3038
3039 // Bail if not viewing a topic
3040 if ( ! bbp_is_single_topic() ) {
3041 return;
3042 }
3043
3044 // Get the topic_status
3045 $topic_status = bbp_get_topic_status();
3046
3047 // Get the topic status
3048 switch ( $topic_status ) {
3049
3050 // Spam notice
3051 case bbp_get_spam_status_id() :
3052 $notice_text = esc_html__( 'This topic is marked as spam.', 'bbpress' );
3053 break;
3054
3055 // Trashed notice
3056 case bbp_get_trash_status_id() :
3057 $notice_text = esc_html__( 'This topic is in the trash.', 'bbpress' );
3058 break;
3059
3060 // Pending notice
3061 case bbp_get_pending_status_id() :
3062 $notice_text = esc_html__( 'This topic is pending moderation.', 'bbpress' );
3063 break;
3064
3065 // Standard status
3066 default :
3067 $notice_text = '';
3068 break;
3069 }
3070
3071 // Filter notice text and bail if empty
3072 $notice_text = apply_filters( 'bbp_topic_notices', $notice_text, $topic_status, bbp_get_topic_id() );
3073 if ( empty( $notice_text ) ) {
3074 return;
3075 }
3076
3077 bbp_add_error( 'topic_notice', $notice_text, 'message' );
3078 }
3079
3080 /**
3081 * Displays topic type select box (normal/sticky/super sticky)
3082 *
3083 * @since 2.0.0 bbPress (r2784)
3084 *
3085 * @deprecated 2.4.0 bbPress (r5059)
3086 *
3087 * @param $args This function supports these arguments:
3088 * - select_id: Select id. Defaults to bbp_stick_topic
3089 * - tab: Deprecated. Tabindex
3090 * - topic_id: Topic id
3091 * - selected: Override the selected option
3092 */
3093 function bbp_topic_type_select( $args = array() ) {
3094 echo bbp_get_form_topic_type_dropdown( $args );
3095 }
3096
3097 /**
3098 * Displays topic type select box (normal/sticky/super sticky)
3099 *
3100 * @since 2.4.0 bbPress (r5059)
3101 *
3102 * @param $args This function supports these arguments:
3103 * - select_id: Select id. Defaults to bbp_stick_topic
3104 * - tab: Deprecated. Tabindex
3105 * - topic_id: Topic id
3106 * - selected: Override the selected option
3107 */
3108 function bbp_form_topic_type_dropdown( $args = array() ) {
3109 echo bbp_get_form_topic_type_dropdown( $args );
3110 }
3111 /**
3112 * Returns topic type select box (normal/sticky/super sticky)
3113 *
3114 * @since 2.4.0 bbPress (r5059)
3115 *
3116 * @param $args This function supports these arguments:
3117 * - select_id: Select id. Defaults to bbp_stick_topic
3118 * - tab: Deprecated. Tabindex
3119 * - topic_id: Topic id
3120 * - selected: Override the selected option
3121 */
3122 function bbp_get_form_topic_type_dropdown( $args = array() ) {
3123
3124 // Parse arguments against default values
3125 $r = bbp_parse_args( $args, array(
3126 'select_id' => 'bbp_stick_topic',
3127 'select_class' => 'bbp_dropdown',
3128 'tab' => false,
3129 'topic_id' => 0,
3130 'selected' => false
3131 ), 'topic_type_select' );
3132
3133 // No specific selected value passed
3134 if ( empty( $r['selected'] ) ) {
3135
3136 // Post value is passed
3137 if ( bbp_is_topic_form_post_request() && isset( $_POST[ $r['select_id'] ] ) ) {
3138 $r['selected'] = sanitize_key( $_POST[ $r['select_id'] ] );
3139
3140 // No Post value passed
3141 } else {
3142
3143 // Edit topic
3144 if ( bbp_is_single_topic() || bbp_is_topic_edit() ) {
3145
3146 // Get current topic id
3147 $r['topic_id'] = bbp_get_topic_id( $r['topic_id'] );
3148
3149 // Topic is super sticky
3150 if ( bbp_is_topic_super_sticky( $r['topic_id'] ) ) {
3151 $r['selected'] = 'super';
3152
3153 // Topic is sticky or normal
3154 } else {
3155 $r['selected'] = bbp_is_topic_sticky( $r['topic_id'], false )
3156 ? 'stick'
3157 : 'unstick';
3158 }
3159 }
3160 }
3161 }
3162
3163 // Start an output buffer, we'll finish it after the select loop
3164 ob_start(); ?>
3165
3166 <select name="<?php echo esc_attr( $r['select_id'] ); ?>" id="<?php echo esc_attr( $r['select_id'] ); ?>_select" class="<?php echo esc_attr( $r['select_class'] ); ?>"<?php bbp_tab_index_attribute( $r['tab'] ); ?>>
3167
3168 <?php foreach ( bbp_get_topic_types( $r['topic_id'] ) as $key => $label ) : ?>
3169
3170 <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $r['selected'] ); ?>><?php echo esc_html( $label ); ?></option>
3171
3172 <?php endforeach; ?>
3173
3174 </select>
3175
3176 <?php
3177
3178 // Filter & return
3179 return apply_filters( 'bbp_get_form_topic_type_dropdown', ob_get_clean(), $r, $args );
3180 }
3181
3182 /**
3183 * Output value topic status dropdown
3184 *
3185 * @since 2.4.0 bbPress (r5059)
3186 *
3187 * @param $args This function supports these arguments:
3188 * - select_id: Select id. Defaults to bbp_topic_status
3189 * - tab: Deprecated. Tabindex
3190 * - topic_id: Topic id
3191 * - selected: Override the selected option
3192 */
3193 function bbp_form_topic_status_dropdown( $args = array() ) {
3194 echo bbp_get_form_topic_status_dropdown( $args );
3195 }
3196 /**
3197 * Returns topic status dropdown
3198 *
3199 * This dropdown is only intended to be seen by users with the 'moderate'
3200 * capability. Because of this, no additional capability checks are performed
3201 * within this function to check available topic statuses.
3202 *
3203 * @since 2.4.0 bbPress (r5059)
3204 *
3205 * @param $args This function supports these arguments:
3206 * - select_id: Select id. Defaults to bbp_topic_status
3207 * - tab: Deprecated. Tabindex
3208 * - topic_id: Topic id
3209 * - selected: Override the selected option
3210 */
3211 function bbp_get_form_topic_status_dropdown( $args = array() ) {
3212
3213 // Parse arguments against default values
3214 $r = bbp_parse_args( $args, array(
3215 'select_id' => 'bbp_topic_status',
3216 'select_class' => 'bbp_dropdown',
3217 'tab' => false,
3218 'topic_id' => 0,
3219 'selected' => false
3220 ), 'topic_open_close_select' );
3221
3222 // No specific selected value passed
3223 if ( empty( $r['selected'] ) ) {
3224
3225 // Post value is passed
3226 if ( bbp_is_topic_form_post_request() && isset( $_POST[ $r['select_id'] ] ) ) {
3227 $r['selected'] = sanitize_key( $_POST[ $r['select_id'] ] );
3228
3229 // No Post value was passed
3230 } else {
3231
3232 // Edit topic
3233 if ( bbp_is_topic_edit() ) {
3234 $r['topic_id'] = bbp_get_topic_id( $r['topic_id'] );
3235 $r['selected'] = bbp_get_topic_status( $r['topic_id'] );
3236
3237 // New topic
3238 } else {
3239 $r['selected'] = bbp_get_public_status_id();
3240 }
3241 }
3242 }
3243
3244 // Start an output buffer, we'll finish it after the select loop
3245 ob_start(); ?>
3246
3247 <select name="<?php echo esc_attr( $r['select_id'] ) ?>" id="<?php echo esc_attr( $r['select_id'] ); ?>_select" class="<?php echo esc_attr( $r['select_class'] ); ?>"<?php bbp_tab_index_attribute( $r['tab'] ); ?>>
3248
3249 <?php foreach ( bbp_get_topic_statuses( $r['topic_id'] ) as $key => $label ) : ?>
3250
3251 <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $r['selected'] ); ?>><?php echo esc_html( $label ); ?></option>
3252
3253 <?php endforeach; ?>
3254
3255 </select>
3256
3257 <?php
3258
3259 // Filter & return
3260 return apply_filters( 'bbp_get_form_topic_status_dropdown', ob_get_clean(), $r, $args );
3261 }
3262
3263 /** Single Topic **************************************************************/
3264
3265 /**
3266 * Output a fancy description of the current topic, including total topics,
3267 * total replies, and last activity.
3268 *
3269 * @since 2.0.0 bbPress (r2860)
3270 *
3271 * @param array $args See {@link bbp_get_single_topic_description()}
3272 */
3273 function bbp_single_topic_description( $args = array() ) {
3274 echo bbp_get_single_topic_description( $args );
3275 }
3276 /**
3277 * Return a fancy description of the current topic, including total topics,
3278 * total replies, and last activity.
3279 *
3280 * @since 2.0.0 bbPress (r2860)
3281 *
3282 * @param array $args This function supports these arguments:
3283 * - topic_id: Topic id
3284 * - before: Before the text
3285 * - after: After the text
3286 * - size: Size of the avatar
3287 * @return string Filtered topic description
3288 */
3289 function bbp_get_single_topic_description( $args = array() ) {
3290
3291 // Parse arguments against default values
3292 $r = bbp_parse_args( $args, array(
3293 'topic_id' => 0,
3294 'before' => '<div class="bbp-template-notice info"><ul><li class="bbp-topic-description">',
3295 'after' => '</li></ul></div>',
3296 'size' => 14
3297 ), 'get_single_topic_description' );
3298
3299 // Validate topic_id
3300 $topic_id = bbp_get_topic_id( $r['topic_id'] );
3301
3302 // Unhook the 'view all' query var adder
3303 remove_filter( 'bbp_get_topic_permalink', 'bbp_add_view_all' );
3304
3305 // Build the topic description
3306 $vc_int = bbp_get_topic_voice_count ( $topic_id, true );
3307 $voice_count = bbp_get_topic_voice_count ( $topic_id, false );
3308 $reply_count = bbp_get_topic_replies_link ( $topic_id );
3309 $time_since = bbp_get_topic_freshness_link( $topic_id );
3310
3311 // Singular/Plural
3312 $voice_count = sprintf( _n( '%s voice', '%s voices', $vc_int, 'bbpress' ), $voice_count );
3313
3314 // Topic has activity (could be from reply or topic author)
3315 $last_active = bbp_get_topic_last_active_id( $topic_id );
3316 if ( ! empty( $vc_int ) && ! empty( $last_active ) ) {
3317 $last_updated_by = bbp_get_author_link( array( 'post_id' => $last_active, 'size' => $r['size'] ) );
3318 $retstr = sprintf( esc_html__( 'This topic has %1$s, %2$s, and was last updated %3$s by %4$s.', 'bbpress' ), $reply_count, $voice_count, $time_since, $last_updated_by );
3319
3320 // Topic has no replies
3321 } elseif ( ! empty( $vc_int ) && ! empty( $reply_count ) ) {
3322 $retstr = sprintf( esc_html__( 'This topic has %1$s and %2$s.', 'bbpress' ), $voice_count, $reply_count );
3323
3324 // Topic has no replies and no voices
3325 } elseif ( empty( $vc_int ) && empty( $reply_count ) ) {
3326 $retstr = esc_html__( 'This topic has no replies.', 'bbpress' );
3327
3328 // Topic is pending
3329 } elseif ( bbp_get_topic_status( $topic_id ) === bbp_get_pending_status_id() ) {
3330 $retstr = esc_html__( 'This topic is pending moderation.', 'bbpress' );
3331
3332 // Fallback
3333 } else {
3334 $retstr = esc_html__( 'This topic is empty.', 'bbpress' );
3335 }
3336
3337 // Add the 'view all' filter back
3338 add_filter( 'bbp_get_topic_permalink', 'bbp_add_view_all' );
3339
3340 // Combine the elements together
3341 $retstr = $r['before'] . $retstr . $r['after'];
3342
3343 // Filter & return
3344 return apply_filters( 'bbp_get_single_topic_description', $retstr, $r, $args );
3345 }
3346
3347 /** Topic Tags ****************************************************************/
3348
3349 /**
3350 * Output the unique id of the topic tag taxonomy
3351 *
3352 * @since 2.0.0 bbPress (r3348)
3353 */
3354 function bbp_topic_tag_tax_id() {
3355 echo bbp_get_topic_tag_tax_id();
3356 }
3357 /**
3358 * Return the unique id of the topic tag taxonomy
3359 *
3360 * @since 2.0.0 bbPress (r3348)
3361 *
3362 * @return string The unique topic tag taxonomy
3363 */
3364 function bbp_get_topic_tag_tax_id() {
3365
3366 // Filter & return
3367 return apply_filters( 'bbp_get_topic_tag_tax_id', bbpress()->topic_tag_tax_id );
3368 }
3369
3370 /**
3371 * Return array of labels used by the topic-tag taxonomy
3372 *
3373 * @since 2.5.0 bbPress (r5129)
3374 *
3375 * @return array
3376 */
3377 function bbp_get_topic_tag_tax_labels() {
3378
3379 // Filter & return
3380 return (array) apply_filters( 'bbp_get_topic_tag_tax_labels', array(
3381 'name' => esc_attr__( 'Topic Tags', 'bbpress' ),
3382 'menu_name' => esc_attr__( 'Topic Tags', 'bbpress' ),
3383 'singular_name' => esc_attr__( 'Topic Tag', 'bbpress' ),
3384 'search_items' => esc_attr__( 'Search Tags', 'bbpress' ),
3385 'popular_items' => esc_attr__( 'Popular Tags', 'bbpress' ),
3386 'all_items' => esc_attr__( 'All Tags', 'bbpress' ),
3387 'parent_item' => esc_attr__( 'Parent Tag', 'bbpress' ),
3388 'parent_item_colon' => esc_attr__( 'Parent Tag:', 'bbpress' ),
3389 'edit_item' => esc_attr__( 'Edit Tag', 'bbpress' ),
3390 'view_item' => esc_attr__( 'View Topic Tag', 'bbpress' ),
3391 'update_item' => esc_attr__( 'Update Tag', 'bbpress' ),
3392 'add_new_item' => esc_attr__( 'Add New Tag', 'bbpress' ),
3393 'new_item_name' => esc_attr__( 'New Tag Name', 'bbpress' ),
3394 'separate_items_with_commas' => esc_attr__( 'Separate topic tags with commas', 'bbpress' ),
3395 'add_or_remove_items' => esc_attr__( 'Add or remove tags', 'bbpress' ),
3396 'choose_from_most_used' => esc_attr__( 'Choose from the most used tags', 'bbpress' ),
3397 'not_found' => esc_attr__( 'No topic tags found.', 'bbpress' ),
3398 'no_terms' => esc_attr__( 'No topic tags', 'bbpress' ),
3399 'items_list_navigation' => esc_attr__( 'Topic tags list navigation', 'bbpress' ),
3400 'items_list' => esc_attr__( 'Topic tags list', 'bbpress' ),
3401 'most_used' => esc_attr__( 'Most used topic tags', 'bbpress' ),
3402 'back_to_items' => esc_attr__( '&larr; Back to Tags', 'bbpress' )
3403 ) );
3404 }
3405
3406 /**
3407 * Return an array of topic-tag taxonomy rewrite settings
3408 *
3409 * @since 2.5.0 bbPress (r5129)
3410 *
3411 * @return array
3412 */
3413 function bbp_get_topic_tag_tax_rewrite() {
3414
3415 // Filter & return
3416 return (array) apply_filters( 'bbp_get_topic_tag_tax_rewrite', array(
3417 'slug' => bbp_get_topic_tag_tax_slug(),
3418 'with_front' => false
3419 ) );
3420 }
3421
3422 /**
3423 * Output the id of the current tag
3424 *
3425 * @since 2.0.0 bbPress (r3109)
3426 *
3427 */
3428 function bbp_topic_tag_id( $tag = '' ) {
3429 echo bbp_get_topic_tag_id( $tag );
3430 }
3431 /**
3432 * Return the id of the current tag
3433 *
3434 * @since 2.0.0 bbPress (r3109)
3435 *
3436 * @return string Term Name
3437 */
3438 function bbp_get_topic_tag_id( $tag = '' ) {
3439
3440 // Get the term
3441 if ( ! empty( $tag ) ) {
3442 $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3443 } else {
3444 $tag = get_query_var( 'term' );
3445 $term = get_queried_object();
3446 }
3447
3448 // Get the term ID
3449 $retval = ! empty( $term->term_id )
3450 ? $term->term_id
3451 : 0;
3452
3453 // Filter & return
3454 return (int) apply_filters( 'bbp_get_topic_tag_id', (int) $retval, $tag, $term );
3455 }
3456
3457 /**
3458 * Output the name of the current tag
3459 *
3460 * @since 2.0.0 bbPress (r3109)
3461 */
3462 function bbp_topic_tag_name( $tag = '' ) {
3463 echo bbp_get_topic_tag_name( $tag );
3464 }
3465 /**
3466 * Return the name of the current tag
3467 *
3468 * @since 2.0.0 bbPress (r3109)
3469 *
3470 * @return string Term Name
3471 */
3472 function bbp_get_topic_tag_name( $tag = '' ) {
3473
3474 // Get the term
3475 if ( ! empty( $tag ) ) {
3476 $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3477 } else {
3478 $tag = get_query_var( 'term' );
3479 $term = get_queried_object();
3480 }
3481
3482 // Get the term name
3483 $retval = ! empty( $term->name )
3484 ? $term->name
3485 : '';
3486
3487 // Filter & return
3488 return apply_filters( 'bbp_get_topic_tag_name', $retval, $tag, $term );
3489 }
3490
3491 /**
3492 * Output the slug of the current tag
3493 *
3494 * @since 2.0.0 bbPress (r3109)
3495 */
3496 function bbp_topic_tag_slug( $tag = '' ) {
3497 echo bbp_get_topic_tag_slug( $tag );
3498 }
3499 /**
3500 * Return the slug of the current tag
3501 *
3502 * @since 2.0.0 bbPress (r3109)
3503 *
3504 * @return string Term Name
3505 */
3506 function bbp_get_topic_tag_slug( $tag = '' ) {
3507
3508 // Get the term
3509 if ( ! empty( $tag ) ) {
3510 $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3511 } else {
3512 $tag = get_query_var( 'term' );
3513 $term = get_queried_object();
3514 }
3515
3516 // Get the term slug
3517 $retval = ! empty( $term->slug )
3518 ? $term->slug
3519 : '';
3520
3521 // Filter & return
3522 return apply_filters( 'bbp_get_topic_tag_slug', $retval, $tag, $term );
3523 }
3524
3525 /**
3526 * Output the link of the current tag
3527 *
3528 * @since 2.0.0 bbPress (r3348)
3529 */
3530 function bbp_topic_tag_link( $tag = '' ) {
3531 echo esc_url( bbp_get_topic_tag_link( $tag ) );
3532 }
3533 /**
3534 * Return the link of the current tag
3535 *
3536 * @since 2.0.0 bbPress (r3348)
3537 *
3538 * @return string Term Name
3539 */
3540 function bbp_get_topic_tag_link( $tag = '' ) {
3541
3542 // Get the term
3543 if ( ! empty( $tag ) ) {
3544 $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3545 } else {
3546 $tag = get_query_var( 'term' );
3547 $term = get_queried_object();
3548 }
3549
3550 // Get the term link
3551 $retval = ! empty( $term->term_id )
3552 ? get_term_link( $term, bbp_get_topic_tag_tax_id() )
3553 : '';
3554
3555 // Filter & return
3556 return apply_filters( 'bbp_get_topic_tag_link', $retval, $tag, $term );
3557 }
3558
3559 /**
3560 * Output the link of the current tag
3561 *
3562 * @since 2.0.0 bbPress (r3348)
3563 */
3564 function bbp_topic_tag_edit_link( $tag = '' ) {
3565 echo esc_url( bbp_get_topic_tag_edit_link( $tag ) );
3566 }
3567 /**
3568 * Return the link of the current tag
3569 *
3570 * @since 2.0.0 bbPress (r3348)
3571 *
3572 * @return string Term Name
3573 */
3574 function bbp_get_topic_tag_edit_link( $tag = '' ) {
3575
3576 // Get the term
3577 if ( ! empty( $tag ) ) {
3578 $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3579 } else {
3580 $tag = get_query_var( 'term' );
3581 $term = get_queried_object();
3582 }
3583
3584 // Get the term's edit link
3585 if ( ! empty( $term->term_id ) ) {
3586
3587 // Pretty or ugly URL
3588 $retval = bbp_use_pretty_urls()
3589 ? user_trailingslashit( trailingslashit( bbp_get_topic_tag_link() ) . bbp_get_edit_slug() )
3590 : add_query_arg( array( bbp_get_edit_rewrite_id() => '1' ), bbp_get_topic_tag_link() );
3591
3592 // No link
3593 } else {
3594 $retval = '';
3595 }
3596
3597 // Filter & return
3598 return apply_filters( 'bbp_get_topic_tag_edit_link', $retval, $tag, $term );
3599 }
3600
3601 /**
3602 * Output the description of the current tag
3603 *
3604 * @since 2.0.0 bbPress (r3109)
3605 */
3606 function bbp_topic_tag_description( $args = array() ) {
3607 echo bbp_get_topic_tag_description( $args );
3608 }
3609 /**
3610 * Return the description of the current tag
3611 *
3612 * @since 2.0.0 bbPress (r3109)
3613 *
3614 * @param array $args before|after|tag
3615 *
3616 * @return string Term Name
3617 */
3618 function bbp_get_topic_tag_description( $args = array() ) {
3619
3620 // Parse arguments against default values
3621 $r = bbp_parse_args( $args, array(
3622 'before' => '<div class="bbp-topic-tag-description"><p>',
3623 'after' => '</p></div>',
3624 'tag' => ''
3625 ), 'get_topic_tag_description' );
3626
3627 // Get the term
3628 if ( ! empty( $r['tag'] ) ) {
3629 $term = get_term_by( 'slug', $r['tag'], bbp_get_topic_tag_tax_id() );
3630 } else {
3631 $tag = $r['tag'] = get_query_var( 'term' );
3632 $term = get_queried_object();
3633 }
3634
3635 // Add before & after if description exists
3636 $retval = ! empty( $term->description )
3637 ? $r['before'] . $term->description . $r['after']
3638 : '';
3639
3640 // Filter & return
3641 return apply_filters( 'bbp_get_topic_tag_description', $retval, $r, $args, $tag, $term );
3642 }
3643
3644 /** Forms *********************************************************************/
3645
3646 /**
3647 * Output the value of topic title field
3648 *
3649 * @since 2.0.0 bbPress (r2976)
3650 */
3651 function bbp_form_topic_title() {
3652 echo bbp_get_form_topic_title();
3653 }
3654 /**
3655 * Return the value of topic title field
3656 *
3657 * @since 2.0.0 bbPress (r2976)
3658 *
3659 * @return string Value of topic title field
3660 */
3661 function bbp_get_form_topic_title() {
3662
3663 // Get _POST data
3664 if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_title'] ) ) {
3665 $topic_title = wp_unslash( $_POST['bbp_topic_title'] );
3666
3667 // Get edit data
3668 } elseif ( bbp_is_topic_edit() ) {
3669 $topic_title = bbp_get_global_post_field( 'post_title', 'raw' );
3670
3671 // No data
3672 } else {
3673 $topic_title = '';
3674 }
3675
3676 // Filter & return
3677 return apply_filters( 'bbp_get_form_topic_title', $topic_title );
3678 }
3679
3680 /**
3681 * Output the value of topic content field
3682 *
3683 * @since 2.0.0 bbPress (r2976)
3684 */
3685 function bbp_form_topic_content() {
3686 echo bbp_get_form_topic_content();
3687 }
3688 /**
3689 * Return the value of topic content field
3690 *
3691 * @since 2.0.0 bbPress (r2976)
3692 *
3693 * @return string Value of topic content field
3694 */
3695 function bbp_get_form_topic_content() {
3696
3697 // Get _POST data
3698 if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_content'] ) ) {
3699 $topic_content = wp_unslash( $_POST['bbp_topic_content'] );
3700
3701 // Get edit data
3702 } elseif ( bbp_is_topic_edit() ) {
3703 $topic_content = bbp_get_global_post_field( 'post_content', 'raw' );
3704
3705 // No data
3706 } else {
3707 $topic_content = '';
3708 }
3709
3710 // Filter & return
3711 return apply_filters( 'bbp_get_form_topic_content', $topic_content );
3712 }
3713
3714 /**
3715 * Allow topic rows to have administrative actions
3716 *
3717 * @since 2.1.0 bbPress (r3653)
3718 *
3719 * @todo Links and filter
3720 */
3721 function bbp_topic_row_actions() {
3722 do_action( 'bbp_topic_row_actions' );
3723 }
3724
3725 /**
3726 * Output value of topic tags field
3727 *
3728 * @since 2.0.0 bbPress (r2976)
3729 */
3730 function bbp_form_topic_tags() {
3731 echo bbp_get_form_topic_tags();
3732 }
3733 /**
3734 * Return value of topic tags field
3735 *
3736 * @since 2.0.0 bbPress (r2976)
3737 *
3738 * @return string Value of topic tags field
3739 */
3740 function bbp_get_form_topic_tags() {
3741
3742 // Default return value
3743 $topic_tags = '';
3744
3745 // Get _POST data
3746 if ( ( bbp_is_topic_form_post_request() || bbp_is_reply_form_post_request() ) && isset( $_POST['bbp_topic_tags'] ) ) {
3747 $topic_tags = wp_unslash( $_POST['bbp_topic_tags'] );
3748
3749 // Get edit data
3750 } elseif ( bbp_is_single_topic() || bbp_is_single_reply() || bbp_is_topic_edit() || bbp_is_reply_edit() ) {
3751
3752 // Determine the topic id based on the post type
3753 switch ( get_post_type() ) {
3754
3755 // Post is a topic
3756 case bbp_get_topic_post_type() :
3757 $topic_id = bbp_get_topic_id( get_the_ID() );
3758 break;
3759
3760 // Post is a reply
3761 case bbp_get_reply_post_type() :
3762 $topic_id = bbp_get_reply_topic_id( get_the_ID() );
3763 break;
3764 }
3765
3766 // Topic exists
3767 if ( ! empty( $topic_id ) ) {
3768
3769 // Topic is spammed so display pre-spam terms
3770 if ( bbp_is_topic_spam( $topic_id ) ) {
3771
3772 // Get pre-spam terms
3773 $spam_terms = get_post_meta( $topic_id, '_bbp_spam_topic_tags', true );
3774 $topic_tags = ( ! empty( $spam_terms ) ) ? implode( ', ', $spam_terms ) : '';
3775
3776 // Topic is not spam so get real terms
3777 } else {
3778 $topic_tags = bbp_get_topic_tag_names( $topic_id );
3779 }
3780 }
3781 }
3782
3783 // Filter & return
3784 return apply_filters( 'bbp_get_form_topic_tags', $topic_tags );
3785 }
3786
3787 /**
3788 * Output value of topic forum
3789 *
3790 * @since 2.0.0 bbPress (r2976)
3791 */
3792 function bbp_form_topic_forum() {
3793 echo bbp_get_form_topic_forum();
3794 }
3795 /**
3796 * Return value of topic forum
3797 *
3798 * @since 2.0.0 bbPress (r2976)
3799 *
3800 * @return string Value of topic content field
3801 */
3802 function bbp_get_form_topic_forum() {
3803
3804 // Get _POST data
3805 if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_forum_id'] ) ) {
3806 $topic_forum = (int) $_POST['bbp_forum_id'];
3807
3808 // Get edit data
3809 } elseif ( bbp_is_topic_edit() ) {
3810 $topic_forum = bbp_get_topic_forum_id();
3811
3812 // No data
3813 } else {
3814 $topic_forum = 0;
3815 }
3816
3817 // Filter & return
3818 return apply_filters( 'bbp_get_form_topic_forum', $topic_forum );
3819 }
3820
3821 /**
3822 * Output checked value of topic subscription
3823 *
3824 * @since 2.0.0 bbPress (r2976)
3825 */
3826 function bbp_form_topic_subscribed() {
3827 echo bbp_get_form_topic_subscribed();
3828 }
3829 /**
3830 * Return checked value of topic subscription
3831 *
3832 * @since 2.0.0 bbPress (r2976)
3833 *
3834 * @return string Checked value of topic subscription
3835 */
3836 function bbp_get_form_topic_subscribed() {
3837
3838 // Default value
3839 $topic_subscribed = false;
3840
3841 // Get _POST data
3842 if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_subscription'] ) ) {
3843 $topic_subscribed = (bool) $_POST['bbp_topic_subscription'];
3844
3845 // Get edit data
3846 } elseif ( bbp_is_topic_edit() || bbp_is_reply_edit() ) {
3847 $post_author = (int) bbp_get_global_post_field( 'post_author', 'raw' );
3848 $topic_subscribed = bbp_is_user_subscribed( $post_author, bbp_get_topic_id() );
3849
3850 // Get current status
3851 } elseif ( bbp_is_single_topic() ) {
3852 $topic_subscribed = bbp_is_user_subscribed( bbp_get_current_user_id(), bbp_get_topic_id() );
3853 }
3854
3855 // Get checked output
3856 $checked = checked( $topic_subscribed, true, false );
3857
3858 // Filter & return
3859 return apply_filters( 'bbp_get_form_topic_subscribed', $checked, $topic_subscribed );
3860 }
3861
3862 /**
3863 * Output checked value of topic log edit field
3864 *
3865 * @since 2.0.0 bbPress (r2976)
3866 */
3867 function bbp_form_topic_log_edit() {
3868 echo bbp_get_form_topic_log_edit();
3869 }
3870 /**
3871 * Return checked value of topic log edit field
3872 *
3873 * @since 2.0.0 bbPress (r2976)
3874 *
3875 * @return string Topic log edit checked value
3876 */
3877 function bbp_get_form_topic_log_edit() {
3878
3879 // Get _POST data
3880 if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_log_topic_edit'] ) ) {
3881 $topic_revision = (bool) $_POST['bbp_log_topic_edit'];
3882
3883 // No data
3884 } else {
3885 $topic_revision = true;
3886 }
3887
3888 // Get checked output
3889 $checked = checked( $topic_revision, true, false );
3890
3891 // Filter & return
3892 return apply_filters( 'bbp_get_form_topic_log_edit', $checked, $topic_revision );
3893 }
3894
3895 /**
3896 * Output the value of the topic edit reason
3897 *
3898 * @since 2.0.0 bbPress (r2976)
3899 */
3900 function bbp_form_topic_edit_reason() {
3901 echo bbp_get_form_topic_edit_reason();
3902 }
3903 /**
3904 * Return the value of the topic edit reason
3905 *
3906 * @since 2.0.0 bbPress (r2976)
3907 *
3908 * @return string Topic edit reason value
3909 */
3910 function bbp_get_form_topic_edit_reason() {
3911
3912 // Get _POST data
3913 if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_edit_reason'] ) ) {
3914 $topic_edit_reason = wp_unslash( $_POST['bbp_topic_edit_reason'] );
3915
3916 // No data
3917 } else {
3918 $topic_edit_reason = '';
3919 }
3920
3921 // Filter & return
3922 return apply_filters( 'bbp_get_form_topic_edit_reason', $topic_edit_reason );
3923 }
3924
3925 /**
3926 * Verify if a POST request came from a failed topic attempt.
3927 *
3928 * Used to avoid cross-site request forgeries when checking posted topic form
3929 * content.
3930 *
3931 * @see bbp_topic_form_fields()
3932 *
3933 * @since 2.6.0 bbPress (r5558)
3934 *
3935 * @return boolean True if is a post request with valid nonce
3936 */
3937 function bbp_is_topic_form_post_request() {
3938
3939 // Bail if not a post request
3940 if ( ! bbp_is_post_request() ) {
3941 return false;
3942 }
3943
3944 // Creating a new topic
3945 if ( bbp_verify_nonce_request( 'bbp-new-topic' ) ) {
3946 return true;
3947 }
3948
3949 // Editing an existing topic
3950 if ( bbp_verify_nonce_request( 'bbp-edit-topic_' . bbp_get_topic_id() ) ) {
3951 return true;
3952 }
3953
3954 return false;
3955 }
3956
3957 /** Warning *******************************************************************/
3958
3959 /**
3960 * Should the topic-lock alert appear?
3961 *
3962 * @since 2.6.0 bbPress (r6342)
3963 *
3964 * @return bool
3965 */
3966 function bbp_show_topic_lock_alert() {
3967
3968 // Default to not showing the alert
3969 $retval = false;
3970
3971 // Get the current topic ID
3972 $topic_id = bbp_get_topic_id();
3973
3974 // Only show on single topic pages
3975 if ( bbp_is_topic_edit() || bbp_is_single_topic() ) {
3976
3977 // Only show to moderators
3978 if ( current_user_can( 'moderate', $topic_id ) ) {
3979
3980 // Locked?
3981 $user_id = bbp_check_post_lock( $topic_id );
3982
3983 // Only show if not locked by the current user
3984 if ( ! empty( $user_id ) && ( bbp_get_current_user_id() !== $user_id ) ) {
3985 $retval = true;
3986 }
3987 }
3988 }
3989
3990 // Filter & return
3991 return (bool) apply_filters( 'bbp_show_topic_lock_alert', $retval, $topic_id );
3992 }
3993
3994 /**
3995 * Output the topic lock description
3996 *
3997 * @since 2.6.0 bbPress (r6343)
3998 *
3999 * @param int $topic_id Optional. Topic id
4000 */
4001 function bbp_topic_lock_description( $topic_id = 0 ) {
4002 echo bbp_get_topic_lock_description( $topic_id );
4003 }
4004 /**
4005 * Return the topic lock description
4006 *
4007 * @since 2.6.0 bbPress (r6343)
4008 *
4009 * @param int $topic_id Optional. Topic id
4010 */
4011 function bbp_get_topic_lock_description( $topic_id = 0 ) {
4012
4013 // Check if topic is edit locked
4014 $topic_id = bbp_get_topic_id( $topic_id );
4015 $user_id = bbp_check_post_lock( $topic_id );
4016 $person = empty( $user_id )
4017 ? esc_html__( 'Nobody', 'bbpress' )
4018 : bbp_get_user_profile_link( $user_id );
4019
4020 // Get the text
4021 $text = sprintf( esc_html__( '%1$s is currently editing this topic.', 'bbpress' ), $person );
4022
4023 // Filter & return
4024 return apply_filters( 'bbp_get_topic_lock_description', $text, $user_id, $topic_id );
4025 }
4026