PluginProbe
bbPress / 2.6.17
bbPress v2.6.17
2.6.17 trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 2.2 2.2.1 All 72 releases
bbpress / includes / replies / template.php

template.php in bbPress 2.6.17, at includes/replies/template.php

2,876 lines 79.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * bbPress Reply 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 * Return the unique id of the custom post type for replies
17 *
18 * @since 2.0.0 bbPress (r2857)
19 *
20 */
21 function bbp_reply_post_type() {
22 echo bbp_get_reply_post_type();
23 }
24 /**
25 * Return the unique id of the custom post type for replies
26 *
27 * @since 2.0.0 bbPress (r2857)
28 *
29 * post type id
30 * @return string The unique reply post type id
31 */
32 function bbp_get_reply_post_type() {
33
34 // Filter & return
35 return apply_filters( 'bbp_get_reply_post_type', bbpress()->reply_post_type );
36 }
37
38 /**
39 * Return array of labels used by the reply post type
40 *
41 * @since 2.5.0 bbPress (r5129)
42 *
43 * @return array
44 */
45 function bbp_get_reply_post_type_labels() {
46
47 // Filter & return
48 return (array) apply_filters(
49 'bbp_get_reply_post_type_labels',
50 array(
51 'name' => esc_attr__( 'Replies', 'bbpress' ),
52 'menu_name' => esc_attr__( 'Replies', 'bbpress' ),
53 'singular_name' => esc_attr_x( 'Reply', 'noun', 'bbpress' ),
54 'all_items' => esc_attr__( 'All Replies', 'bbpress' ),
55 'add_new' => esc_attr__( 'Add New', 'bbpress' ),
56 'add_new_item' => esc_attr__( 'Create New Reply', 'bbpress' ),
57 'edit' => esc_attr__( 'Edit', 'bbpress' ),
58 'edit_item' => esc_attr__( 'Edit Reply', 'bbpress' ),
59 'new_item' => esc_attr__( 'New Reply', 'bbpress' ),
60 'view' => esc_attr__( 'View Reply', 'bbpress' ),
61 'view_item' => esc_attr__( 'View Reply', 'bbpress' ),
62 'view_items' => esc_attr__( 'View Replies', 'bbpress' ),
63 'search_items' => esc_attr__( 'Search Replies', 'bbpress' ),
64 'not_found' => esc_attr__( 'No replies found', 'bbpress' ),
65 'not_found_in_trash' => esc_attr__( 'No replies found in Trash', 'bbpress' ),
66 'filter_items_list' => esc_attr__( 'Filter replies list', 'bbpress' ),
67 'items_list' => esc_attr__( 'Replies list', 'bbpress' ),
68 'items_list_navigation' => esc_attr__( 'Replies list navigation', 'bbpress' ),
69 'parent_item_colon' => esc_attr__( 'Parent Topic:', 'bbpress' ),
70 'archives' => esc_attr__( 'Forum Replies', 'bbpress' ),
71 'attributes' => esc_attr__( 'Reply Attributes', 'bbpress' ),
72 'insert_into_item' => esc_attr__( 'Insert into reply', 'bbpress' ),
73 'uploaded_to_this_item' => esc_attr__( 'Uploaded to this reply', 'bbpress' ),
74 'featured_image' => esc_attr__( 'Reply Image', 'bbpress' ),
75 'set_featured_image' => esc_attr__( 'Set reply image', 'bbpress' ),
76 'remove_featured_image' => esc_attr__( 'Remove reply image', 'bbpress' ),
77 'use_featured_image' => esc_attr__( 'Use as reply image', 'bbpress' ),
78 'item_published' => esc_attr__( 'Reply published.', 'bbpress' ),
79 'item_published_privately' => esc_attr__( 'Reply published privately.', 'bbpress' ),
80 'item_reverted_to_draft' => esc_attr__( 'Reply reverted to draft.', 'bbpress' ),
81 'item_scheduled' => esc_attr__( 'Reply scheduled.', 'bbpress' ),
82 'item_updated' => esc_attr__( 'Reply updated.', 'bbpress' )
83 )
84 );
85 }
86
87 /**
88 * Return array of reply post type rewrite settings
89 *
90 * @since 2.5.0 bbPress (r5129)
91 *
92 * @return array
93 */
94 function bbp_get_reply_post_type_rewrite() {
95
96 // Filter & return
97 return (array) apply_filters(
98 'bbp_get_reply_post_type_rewrite',
99 array(
100 'slug' => bbp_get_reply_slug(),
101 'with_front' => false
102 )
103 );
104 }
105
106 /**
107 * Return array of features the reply post type supports
108 *
109 * @since 2.5.0 bbPress (r5129)
110 *
111 * @return array
112 */
113 function bbp_get_reply_post_type_supports() {
114
115 // Filter & return
116 return (array) apply_filters(
117 'bbp_get_reply_post_type_supports',
118 array(
119 'title',
120 'editor',
121 'revisions'
122 )
123 );
124 }
125
126 /** Reply Loop Functions ******************************************************/
127
128 /**
129 * The main reply loop. WordPress makes this easy for us
130 *
131 * @since 2.0.0 bbPress (r2553)
132 *
133 * @param array $args All the arguments supported by {@link WP_Query}
134 * @return object Multidimensional array of reply information
135 */
136 function bbp_has_replies( $args = array() ) {
137
138 /** Defaults **************************************************************/
139
140 // Other defaults
141 $default_reply_search = bbp_sanitize_search_request( 'rs' );
142 $default_post_parent = ( bbp_is_single_topic() ) ? bbp_get_topic_id() : 'any';
143 $default_post_type = ( bbp_is_single_topic() && bbp_show_lead_topic() ) ? bbp_get_reply_post_type() : array( bbp_get_topic_post_type(), bbp_get_reply_post_type() );
144 $default_thread_replies = (bool) ( bbp_is_single_topic() && bbp_thread_replies() );
145
146 // Default query args
147 $default = array(
148 'post_type' => $default_post_type, // Only replies
149 'post_parent' => $default_post_parent, // Of this topic
150 'posts_per_page' => bbp_get_replies_per_page(), // This many
151 'paged' => bbp_get_paged(), // On this page
152 'orderby' => 'date', // Sorted by date
153 'order' => 'ASC', // Oldest to newest
154 'hierarchical' => $default_thread_replies, // Hierarchical replies
155 'ignore_sticky_posts' => true, // Stickies not supported
156 'update_post_term_cache' => false, // No terms to cache
157
158 // Conditionally prime the cache for all related posts
159 'update_post_family_cache' => true
160 );
161
162 // Only add 's' arg if searching for replies
163 // See https://bbpress.trac.wordpress.org/ticket/2607
164 if ( ! empty( $default_reply_search ) ) {
165 $default['s'] = $default_reply_search;
166 }
167
168 // What are the default allowed statuses (based on user caps)
169 if ( bbp_get_view_all( 'edit_others_replies' ) ) {
170
171 // Default view=all statuses
172 $post_statuses = array_keys( bbp_get_topic_statuses() );
173
174 // Add support for private status
175 if ( current_user_can( 'read_private_replies' ) ) {
176 $post_statuses[] = bbp_get_private_status_id();
177 }
178
179 // Join post statuses together
180 $default['post_status'] = $post_statuses;
181
182 // Lean on the 'perm' query var value of 'readable' to provide statuses
183 } else {
184 $default['perm'] = 'readable';
185 }
186
187 /** Setup *****************************************************************/
188
189 // Parse arguments against default values
190 $r = bbp_parse_args( $args, $default, 'has_replies' );
191
192 // Set posts_per_page value if replies are threaded
193 $replies_per_page = (int) $r['posts_per_page'];
194 if ( true === $r['hierarchical'] ) {
195 $r['posts_per_page'] = -1;
196 }
197
198 // Get bbPress
199 $bbp = bbpress();
200
201 // Call the query
202 $bbp->reply_query = new WP_Query( $r );
203
204 // Maybe prime the post author caches
205 if ( ! empty( $r['update_post_family_cache'] ) ) {
206 bbp_update_post_family_caches( $bbp->reply_query->posts );
207 }
208
209 // Add pagination values to query object
210 $bbp->reply_query->posts_per_page = (int) $replies_per_page;
211 $bbp->reply_query->paged = (int) $r['paged'];
212
213 // Never home, regardless of what parse_query says
214 $bbp->reply_query->is_home = false;
215
216 // Reset is_single if single topic
217 if ( bbp_is_single_topic() ) {
218 $bbp->reply_query->is_single = true;
219 }
220
221 // Only add reply to if query returned results
222 if ( ! empty( $bbp->reply_query->found_posts ) ) {
223
224 // Get reply to for each reply
225 foreach ( $bbp->reply_query->posts as &$post ) {
226
227 // Check for reply post type
228 if ( bbp_get_reply_post_type() === $post->post_type ) {
229 $reply_to = bbp_get_reply_to( $post->ID );
230
231 // Make sure it's a reply to a reply
232 if ( empty( $reply_to ) || ( bbp_get_reply_topic_id( $post->ID ) === $reply_to ) ) {
233 $reply_to = 0;
234 }
235
236 // Add reply_to to the post object so we can walk it later
237 $post->reply_to = $reply_to;
238 }
239 }
240 }
241
242 // Only add pagination if query returned results
243 if ( ! empty( $bbp->reply_query->found_posts ) && ! empty( $bbp->reply_query->posts_per_page ) ) {
244
245 // Figure out total pages
246 if ( true === $r['hierarchical'] ) {
247 $walker = new BBP_Walker_Reply();
248 $total_pages = ceil( $walker->get_number_of_root_elements( $bbp->reply_query->posts ) / $bbp->reply_query->posts_per_page );
249 } else {
250
251 // Total for pagination boundaries
252 $total_pages = ( $bbp->reply_query->posts_per_page === $bbp->reply_query->found_posts )
253 ? 1
254 : ceil( $bbp->reply_query->found_posts / $bbp->reply_query->posts_per_page );
255
256 // Pagination settings with filter
257 $bbp_replies_pagination = apply_filters(
258 'bbp_replies_pagination',
259 array(
260 'base' => bbp_get_replies_pagination_base( bbp_get_topic_id() ),
261 'total' => $total_pages,
262 'current' => $bbp->reply_query->paged
263 )
264 );
265
266 // Add pagination to query object
267 $bbp->reply_query->pagination_links = bbp_paginate_links( $bbp_replies_pagination );
268 }
269 }
270
271 // Filter & return
272 return apply_filters( 'bbp_has_replies', $bbp->reply_query->have_posts(), $bbp->reply_query );
273 }
274
275 /**
276 * Whether there are more replies available in the loop
277 *
278 * @since 2.0.0 bbPress (r2553)
279 *
280 * @return object Replies information
281 */
282 function bbp_replies() {
283
284 // Put into variable to check against next
285 $have_posts = bbpress()->reply_query->have_posts();
286
287 // Reset the post data when finished
288 if ( empty( $have_posts ) ) {
289 wp_reset_postdata();
290 }
291
292 return $have_posts;
293 }
294
295 /**
296 * Loads up the current reply in the loop
297 *
298 * @since 2.0.0 bbPress (r2553)
299 *
300 * @return object Reply information
301 */
302 function bbp_the_reply() {
303 return bbpress()->reply_query->the_post();
304 }
305
306 /**
307 * Output reply id
308 *
309 * @since 2.0.0 bbPress (r2553)
310 *
311 * @param $reply_id Optional. Used to check emptiness
312 */
313 function bbp_reply_id( $reply_id = 0 ) {
314 echo bbp_get_reply_id( $reply_id );
315 }
316 /**
317 * Return the id of the reply in a replies loop
318 *
319 * @since 2.0.0 bbPress (r2553)
320 *
321 * @param $reply_id Optional. Used to check emptiness
322 * @return int The reply id
323 */
324 function bbp_get_reply_id( $reply_id = 0 ) {
325 $bbp = bbpress();
326 $wp_query = bbp_get_wp_query();
327
328 // Easy empty checking
329 if ( ! empty( $reply_id ) && is_numeric( $reply_id ) ) {
330 $bbp_reply_id = $reply_id;
331
332 // Currently inside a replies loop
333 } elseif ( ! empty( $bbp->reply_query->in_the_loop ) && isset( $bbp->reply_query->post->ID ) ) {
334 $bbp_reply_id = $bbp->reply_query->post->ID;
335
336 // Currently inside a search loop
337 } elseif ( ! empty( $bbp->search_query->in_the_loop ) && isset( $bbp->search_query->post->ID ) && bbp_is_reply( $bbp->search_query->post->ID ) ) {
338 $bbp_reply_id = $bbp->search_query->post->ID;
339
340 // Currently viewing a forum
341 } elseif ( ( bbp_is_single_reply() || bbp_is_reply_edit() ) && ! empty( $bbp->current_reply_id ) ) {
342 $bbp_reply_id = $bbp->current_reply_id;
343
344 // Currently viewing a reply
345 } elseif ( ( bbp_is_single_reply() || bbp_is_reply_edit() ) && isset( $wp_query->post->ID ) ) {
346 $bbp_reply_id = $wp_query->post->ID;
347
348 // Fallback
349 } else {
350 $bbp_reply_id = 0;
351 }
352
353 // Filter & return
354 return (int) apply_filters( 'bbp_get_reply_id', $bbp_reply_id, $reply_id );
355 }
356
357 /**
358 * Gets a reply
359 *
360 * @since 2.0.0 bbPress (r2787)
361 *
362 * @param int|object $reply reply id or reply object
363 * @param string $output Optional. OBJECT, ARRAY_A, or ARRAY_N. Default = OBJECT
364 * @param string $filter Optional Sanitation filter. See {@link sanitize_post()}
365 * @return mixed Null if error or reply (in specified form) if success
366 */
367 function bbp_get_reply( $reply, $output = OBJECT, $filter = 'raw' ) {
368
369 // Maybe get ID from empty or int
370 if ( empty( $reply ) || is_numeric( $reply ) ) {
371 $reply = bbp_get_reply_id( $reply );
372 }
373
374 // Bail if no post object
375 $reply = get_post( $reply, OBJECT, $filter );
376 if ( empty( $reply ) ) {
377 return $reply;
378 }
379
380 // Bail if not correct post type
381 if ( bbp_get_reply_post_type() !== $reply->post_type ) {
382 return null;
383 }
384
385 // Default return value is OBJECT
386 $retval = $reply;
387
388 // Array A
389 if ( ARRAY_A === $output ) {
390 $retval = get_object_vars( $reply );
391
392 // Array N
393 } elseif ( ARRAY_N === $output ) {
394 $retval = array_values( get_object_vars( $reply ) );
395 }
396
397 // Filter & return
398 return apply_filters( 'bbp_get_reply', $retval, $reply, $output, $filter );
399 }
400
401 /**
402 * Output the link to the reply in the reply loop
403 *
404 * @since 2.0.0 bbPress (r2553)
405 *
406 * @param int $reply_id Optional. Reply id
407 */
408 function bbp_reply_permalink( $reply_id = 0 ) {
409 echo esc_url( bbp_get_reply_permalink( $reply_id ) );
410 }
411 /**
412 * Return the link to the reply
413 *
414 * @since 2.0.0 bbPress (r2553)
415 *
416 * @param int $reply_id Optional. Reply id
417 *
418 * @return string Permanent link to reply
419 */
420 function bbp_get_reply_permalink( $reply_id = 0 ) {
421 $reply_id = bbp_get_reply_id( $reply_id );
422
423 // Filter & return
424 return apply_filters( 'bbp_get_reply_permalink', get_permalink( $reply_id ), $reply_id );
425 }
426
427 /**
428 * Output the paginated url to the reply in the reply loop
429 *
430 * @since 2.0.0 bbPress (r2679)
431 *
432 * @param int $reply_id Optional. Reply id
433 */
434 function bbp_reply_url( $reply_id = 0 ) {
435 echo esc_url( bbp_get_reply_url( $reply_id ) );
436 }
437 /**
438 * Return the paginated url to the reply in the reply loop
439 *
440 * @since 2.0.0 bbPress (r2679)
441 *
442 * @param int $reply_id Optional. Reply id
443 * @param string $redirect_to Optional. Pass a redirect value for use with
444 * shortcodes and other fun things.
445 * @return string Link to reply relative to paginated topic
446 */
447 function bbp_get_reply_url( $reply_id = 0, $redirect_to = '' ) {
448
449 // Set needed variables
450 $reply_id = bbp_get_reply_id( $reply_id );
451 $topic_id = 0;
452
453 // Juggle reply & topic IDs for unpretty URL formatting
454 if ( bbp_is_reply( $reply_id ) ) {
455 $topic_id = bbp_get_reply_topic_id( $reply_id );
456 $topic = bbp_get_topic( $topic_id );
457 } elseif ( bbp_is_topic( $reply_id ) ) {
458 $topic_id = bbp_get_topic_id( $reply_id );
459 $topic = bbp_get_topic( $topic_id );
460 $reply_id = $topic_id;
461 }
462
463 // Hierarchical reply page
464 if ( bbp_thread_replies() ) {
465 $reply_page = 1;
466
467 // Standard reply page
468 } else {
469 $reply_page = ceil( (int) bbp_get_reply_position( $reply_id, $topic_id ) / (int) bbp_get_replies_per_page() );
470 }
471
472 // Get links & URLS
473 $reply_hash = '#post-' . $reply_id;
474 $topic_link = bbp_get_topic_permalink( $topic_id, $redirect_to );
475 $topic_url = remove_query_arg( 'view', $topic_link );
476
477 // Get vars needed to support pending topics with unpretty links
478 $has_slug = ! empty( $topic ) ? $topic->post_name : '';
479 $pretty = bbp_use_pretty_urls();
480 $published = bbp_is_topic_public( $topic_id );
481
482 // Don't include pagination if on first page
483 if ( 1 >= $reply_page ) {
484
485 // Pretty permalinks
486 if ( ! empty( $has_slug ) && ! empty( $pretty ) && ! empty( $published ) ) {
487 $url = user_trailingslashit( $topic_url ) . $reply_hash;
488
489 // Unpretty links
490 } else {
491 $url = $topic_url . $reply_hash;
492 }
493
494 // Include pagination
495 // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
496 } else {
497
498 // Pretty permalinks
499 if ( ! empty( $has_slug ) && ! empty( $pretty ) && ! empty( $published ) ) {
500 $url = trailingslashit( $topic_url ) . trailingslashit( bbp_get_paged_slug() ) . $reply_page;
501 $url = user_trailingslashit( $url ) . $reply_hash;
502
503 // Unpretty links
504 } else {
505 $url = add_query_arg( 'paged', $reply_page, $topic_url ) . $reply_hash;
506 }
507 }
508
509 // Add topic view query arg back to end if it is set
510 if ( bbp_get_view_all() ) {
511 $url = bbp_add_view_all( $url );
512 }
513
514 // Filter & return
515 return apply_filters( 'bbp_get_reply_url', $url, $reply_id, $redirect_to );
516 }
517
518 /**
519 * Output the title of the reply
520 *
521 * @since 2.0.0 bbPress (r2553)
522 *
523 * @param int $reply_id Optional. Reply id
524 */
525 function bbp_reply_title( $reply_id = 0 ) {
526 echo bbp_get_reply_title( $reply_id );
527 }
528
529 /**
530 * Return the title of the reply
531 *
532 * @since 2.0.0 bbPress (r2553)
533 *
534 * @param int $reply_id Optional. Reply id
535 * @return string Title of reply
536 */
537 function bbp_get_reply_title( $reply_id = 0 ) {
538 $reply_id = bbp_get_reply_id( $reply_id );
539 $title = get_the_title( $reply_id );
540
541 // Filter & return
542 return apply_filters( 'bbp_get_reply_title', $title, $reply_id );
543 }
544
545 /**
546 * Get empty reply title fallback.
547 *
548 * @since 2.5.0 bbPress (r5177)
549 *
550 * @param string $post_title Required. Reply Title
551 * @param int $post_id Required. Reply ID
552 * @return string Title of reply
553 */
554 function bbp_get_reply_title_fallback( $post_title = '', $post_id = 0 ) {
555
556 // Bail if title not empty, or post is not a reply
557 if ( ! empty( $post_title ) || ! bbp_is_reply( $post_id ) ) {
558 return $post_title;
559 }
560
561 // Get reply topic title.
562 $topic_title = bbp_get_reply_topic_title( $post_id );
563
564 // Get empty reply title fallback.
565 $reply_title = sprintf(
566 /* translators: %s: Topic title */
567 esc_html__( 'Reply To: %s', 'bbpress' ),
568 $topic_title
569 );
570
571 // Filter & return
572 return apply_filters( 'bbp_get_reply_title_fallback', $reply_title, $post_id, $topic_title );
573 }
574
575 /**
576 * Output the content of the reply
577 *
578 * @since 2.0.0 bbPress (r2553)
579 *
580 * @param int $reply_id Optional. reply id
581 */
582 function bbp_reply_content( $reply_id = 0 ) {
583 echo bbp_get_reply_content( $reply_id );
584 }
585 /**
586 * Return the content of the reply
587 *
588 * @since 2.0.0 bbPress (r2780)
589 *
590 * @param int $reply_id Optional. reply id
591 * @return string Content of the reply
592 */
593 function bbp_get_reply_content( $reply_id = 0 ) {
594 $reply_id = bbp_get_reply_id( $reply_id );
595
596 // Check if password is required
597 if ( post_password_required( $reply_id ) ) {
598 return get_the_password_form();
599 }
600
601 $content = get_post_field( 'post_content', $reply_id );
602
603 // Filter & return
604 return apply_filters( 'bbp_get_reply_content', $content, $reply_id );
605 }
606
607 /**
608 * Output the excerpt of the reply
609 *
610 * @since 2.0.0 bbPress (r2751)
611 *
612 * @param int $reply_id Optional. Reply id
613 * @param int $length Optional. Length of the excerpt. Defaults to 100 letters
614 */
615 function bbp_reply_excerpt( $reply_id = 0, $length = 100 ) {
616 echo bbp_get_reply_excerpt( $reply_id, $length );
617 }
618 /**
619 * Return the excerpt of the reply
620 *
621 * @since 2.0.0 bbPress (r2751)
622 *
623 * @param int $reply_id Optional. Reply id
624 * @param int $length Optional. Length of the excerpt. Defaults to 100
625 * letters
626 * @return string Reply Excerpt
627 */
628 function bbp_get_reply_excerpt( $reply_id = 0, $length = 100 ) {
629 $reply_id = bbp_get_reply_id( $reply_id );
630 $length = (int) $length;
631 $excerpt = get_post_field( 'post_excerpt', $reply_id );
632
633 if ( empty( $excerpt ) ) {
634 $excerpt = bbp_get_reply_content( $reply_id );
635 }
636
637 $excerpt = trim ( strip_tags( $excerpt ) );
638
639 // Multibyte support
640 if ( function_exists( 'mb_strlen' ) ) {
641 $excerpt_length = mb_strlen( $excerpt );
642 } else {
643 $excerpt_length = strlen( $excerpt );
644 }
645
646 if ( ! empty( $length ) && ( $excerpt_length > $length ) ) {
647 $excerpt = mb_substr( $excerpt, 0, $length - 1 );
648 $excerpt .= '&hellip;';
649 }
650
651 // Filter & return
652 return apply_filters( 'bbp_get_reply_excerpt', $excerpt, $reply_id, $length );
653 }
654
655 /**
656 * Output the post date and time of a reply
657 *
658 * @since 2.2.0 bbPress (r4155)
659 *
660 * @param int $reply_id Optional. Reply id.
661 * @param bool $humanize Optional. Humanize output using time_since
662 * @param bool $gmt Optional. Use GMT
663 */
664 function bbp_reply_post_date( $reply_id = 0, $humanize = false, $gmt = false ) {
665 echo bbp_get_reply_post_date( $reply_id, $humanize, $gmt );
666 }
667 /**
668 * Return the post date and time of a reply
669 *
670 * @since 2.2.0 bbPress (r4155)
671 *
672 * @param int $reply_id Optional. Reply id.
673 * @param bool $humanize Optional. Humanize output using time_since
674 * @param bool $gmt Optional. Use GMT
675 * @return string
676 */
677 function bbp_get_reply_post_date( $reply_id = 0, $humanize = false, $gmt = false ) {
678 $reply_id = bbp_get_reply_id( $reply_id );
679
680 // 4 days, 4 hours ago
681 if ( ! empty( $humanize ) ) {
682 $gmt_s = ! empty( $gmt ) ? 'G' : 'U';
683 $date = get_post_time( $gmt_s, $gmt, $reply_id );
684 $time = false; // For filter below
685 $result = bbp_get_time_since( $date );
686
687 // August 4, 2012 at 2:37 pm
688 } else {
689 $date = get_post_time( get_option( 'date_format' ), $gmt, $reply_id, true );
690 $time = get_post_time( get_option( 'time_format' ), $gmt, $reply_id, true );
691 /* translators: 1: Date, 2: Time */
692 $result = sprintf( _x( '%1$s at %2$s', 'date at time', 'bbpress' ), $date, $time );
693 }
694
695 // Filter & return
696 return apply_filters( 'bbp_get_reply_post_date', $result, $reply_id, $humanize, $gmt, $date, $time );
697 }
698
699 /**
700 * Append revisions to the reply content
701 *
702 * @since 2.0.0 bbPress (r2782)
703 *
704 * @param string $content Optional. Content to which we need to append the revisions to
705 * @param int $reply_id Optional. Reply id
706 * @return string Content with the revisions appended
707 */
708 function bbp_reply_content_append_revisions( $content = '', $reply_id = 0 ) {
709
710 // Bail if in admin or feed
711 if ( is_admin() || is_feed() ) {
712 return $content;
713 }
714
715 // Validate the ID
716 $reply_id = bbp_get_reply_id( $reply_id );
717
718 // Filter & return
719 return apply_filters( 'bbp_reply_append_revisions', $content . bbp_get_reply_revision_log( $reply_id ), $content, $reply_id );
720 }
721
722 /**
723 * Output the revision log of the reply
724 *
725 * @since 2.0.0 bbPress (r2782)
726 *
727 * @param int $reply_id Optional. Reply id
728 */
729 function bbp_reply_revision_log( $reply_id = 0 ) {
730 echo bbp_get_reply_revision_log( $reply_id );
731 }
732 /**
733 * Return the formatted revision log of the reply
734 *
735 * @since 2.0.0 bbPress (r2782)
736 *
737 * @param int $reply_id Optional. Reply id
738 * @return string Revision log of the reply
739 */
740 function bbp_get_reply_revision_log( $reply_id = 0 ) {
741
742 // Create necessary variables
743 $reply_id = bbp_get_reply_id( $reply_id );
744
745 // Show the topic reply log if this is a topic in a reply loop
746 if ( bbp_is_topic( $reply_id ) ) {
747 return bbp_get_topic_revision_log( $reply_id );
748 }
749
750 // Get the reply revision log (out of post meta
751 $revision_log = bbp_get_reply_raw_revision_log( $reply_id );
752
753 // Check reply and revision log exist
754 if ( empty( $reply_id ) || empty( $revision_log ) || ! is_array( $revision_log ) ) {
755 return false;
756 }
757
758 // Get the actual revisions
759 $revisions = bbp_get_reply_revisions( $reply_id );
760 if ( empty( $revisions ) ) {
761 return false;
762 }
763
764 $r = "\n\n" . '<ul id="bbp-reply-revision-log-' . esc_attr( $reply_id ) . '" class="bbp-reply-revision-log">' . "\n\n";
765
766 // Loop through revisions
767 foreach ( (array) $revisions as $revision ) {
768
769 if ( empty( $revision_log[ $revision->ID ] ) ) {
770 $author_id = $revision->post_author;
771 $reason = '';
772 } else {
773 $author_id = $revision_log[ $revision->ID ]['author'];
774 $reason = $revision_log[ $revision->ID ]['reason'];
775 }
776
777 $since = bbp_get_time_since( bbp_convert_date( $revision->post_modified ) );
778 $author = bbp_get_author_link(
779 array(
780 'size' => 14,
781 'link_text' => bbp_get_reply_author_display_name( $revision->ID ),
782 'post_id' => $revision->ID
783 )
784 );
785
786 $r .= "\t" . '<li id="bbp-reply-revision-log-' . esc_attr( $reply_id ) . '-item-' . esc_attr( $revision->ID ) . '" class="bbp-reply-revision-log-item">' . "\n";
787 if ( ! empty( $reason ) ) {
788 /* translators: 1: Time since modification, 2: Author linked display name, 3: Modification reason */
789 $r .= "\t\t" . sprintf( esc_html__( 'This reply was modified %1$s by %2$s. Reason: %3$s', 'bbpress' ), esc_html( $since ), $author, esc_html( $reason ) ) . "\n";
790 } else {
791 /* translators: 1: Time since modification, 2: Author linked display name */
792 $r .= "\t\t" . sprintf( esc_html__( 'This reply was modified %1$s by %2$s.', 'bbpress' ), esc_html( $since ), $author ) . "\n";
793 }
794
795 $r .= "\t" . '</li>' . "\n";
796 }
797
798 $r .= "\n" . '</ul>' . "\n\n";
799
800 // Filter & return
801 return apply_filters( 'bbp_get_reply_revision_log', $r, $reply_id );
802 }
803 /**
804 * Return the raw revision log of the reply
805 *
806 * @since 2.0.0 bbPress (r2782)
807 *
808 * @param int $reply_id Optional. Reply id
809 * @return string Raw revision log of the reply
810 */
811 function bbp_get_reply_raw_revision_log( $reply_id = 0 ) {
812 $reply_id = bbp_get_reply_id( $reply_id );
813 $revision_log = get_post_meta( $reply_id, '_bbp_revision_log', true );
814 $revision_log = ! empty( $revision_log )
815 ? $revision_log
816 : array();
817
818 // Filter & return
819 return apply_filters( 'bbp_get_reply_raw_revision_log', $revision_log, $reply_id );
820 }
821
822 /**
823 * Return the revisions of the reply
824 *
825 * @since 2.0.0 bbPress (r2782)
826 *
827 * @param int $reply_id Optional. Reply id
828 * @return WP_Post[]|int[] reply revisions
829 */
830 function bbp_get_reply_revisions( $reply_id = 0 ) {
831 $reply_id = bbp_get_reply_id( $reply_id );
832 $revisions = wp_get_post_revisions( $reply_id, array( 'order' => 'ASC' ) );
833
834 // Filter & return
835 return apply_filters( 'bbp_get_reply_revisions', $revisions, $reply_id );
836 }
837
838 /**
839 * Return the revision count of the reply
840 *
841 * @since 2.0.0 bbPress (r2782)
842 *
843 * @param int $reply_id Optional. Reply id
844 * @param boolean $integer Optional. Whether or not to format the result
845 * @return string reply revision count
846 */
847 function bbp_get_reply_revision_count( $reply_id = 0, $integer = false ) {
848 $reply_id = bbp_get_reply_id( $reply_id );
849 $count = count( bbp_get_reply_revisions( $reply_id ) );
850 $filter = ( true === $integer )
851 ? 'bbp_get_reply_revision_count_int'
852 : 'bbp_get_reply_revision_count';
853
854 return apply_filters( $filter, $count, $reply_id );
855 }
856
857 /**
858 * Output the status of the reply
859 *
860 * @since 2.0.0 bbPress (r2667)
861 *
862 * @param int $reply_id Optional. Reply id
863 */
864 function bbp_reply_status( $reply_id = 0 ) {
865 echo bbp_get_reply_status( $reply_id );
866 }
867 /**
868 * Return the status of the reply
869 *
870 * @since 2.0.0 bbPress (r2667)
871 *
872 * @param int $reply_id Optional. Reply id
873 * @return string Status of reply
874 */
875 function bbp_get_reply_status( $reply_id = 0 ) {
876 $reply_id = bbp_get_reply_id( $reply_id );
877
878 // Filter & return
879 return apply_filters( 'bbp_get_reply_status', get_post_status( $reply_id ), $reply_id );
880 }
881
882 /**
883 * Is the reply publicly viewable?
884 *
885 * See bbp_get_public_reply_statuses() for public statuses.
886 *
887 * @since 2.6.0 bbPress (r6391)
888 *
889 * @param int $reply_id Optional. Reply id
890 * @return bool True if public, false if not.
891 */
892 function bbp_is_reply_public( $reply_id = 0 ) {
893 $reply_id = bbp_get_reply_id( $reply_id );
894 $status = bbp_get_reply_status( $reply_id );
895 $public = bbp_get_public_reply_statuses();
896 $is_public = in_array( $status, $public, true );
897
898 // Filter & return
899 return (bool) apply_filters( 'bbp_is_reply_public', $is_public, $reply_id );
900 }
901
902 /**
903 * Is the reply not spam or deleted?
904 *
905 * @since 2.0.0 bbPress (r3496)
906 * @since 2.6.0 bbPress (r6922) Returns false if topic is also not published
907 *
908 * @param int $reply_id Optional. Topic id
909 * @return bool True if published, false if not.
910 */
911 function bbp_is_reply_published( $reply_id = 0 ) {
912 $reply_id = bbp_get_reply_id( $reply_id );
913 $topic_id = bbp_get_reply_topic_id( $reply_id );
914 $status = bbp_get_public_status_id();
915 $topic_status = bbp_is_topic_published( $topic_id );
916 $reply_status = ( bbp_get_reply_status( $reply_id ) === $status );
917 $retval = ( $reply_status && $topic_status );
918
919 // Filter & return
920 return (bool) apply_filters( 'bbp_is_reply_published', (bool) $retval, $reply_id );
921 }
922
923 /**
924 * Is the reply marked as spam?
925 *
926 * @since 2.0.0 bbPress (r2740)
927 *
928 * @param int $reply_id Optional. Reply id
929 * @return bool True if spam, false if not.
930 */
931 function bbp_is_reply_spam( $reply_id = 0 ) {
932 $reply_id = bbp_get_reply_id( $reply_id );
933 $status = bbp_get_spam_status_id();
934 $reply_status = bbp_get_reply_status( $reply_id ) === $status;
935
936 // Filter & return
937 return (bool) apply_filters( 'bbp_is_reply_spam', (bool) $reply_status, $reply_id );
938 }
939
940 /**
941 * Is the reply trashed?
942 *
943 * @since 2.0.0 bbPress (r2884)
944 *
945 * @param int $reply_id Optional. Topic id
946 * @return bool True if spam, false if not.
947 */
948 function bbp_is_reply_trash( $reply_id = 0 ) {
949 $reply_id = bbp_get_reply_id( $reply_id );
950 $status = bbp_get_trash_status_id();
951 $reply_status = bbp_get_reply_status( $reply_id ) === $status;
952
953 // Filter & return
954 return (bool) apply_filters( 'bbp_is_reply_trash', (bool) $reply_status, $reply_id );
955 }
956
957 /**
958 * Is the reply pending?
959 *
960 * @since 2.6.0 bbPress (r5507)
961 *
962 * @param int $reply_id Optional. Topic id
963 * @return bool True if pending, false if not.
964 */
965 function bbp_is_reply_pending( $reply_id = 0 ) {
966 $reply_id = bbp_get_reply_id( $reply_id );
967 $status = bbp_get_pending_status_id();
968 $reply_status = bbp_get_reply_status( $reply_id ) === $status;
969
970 // Filter & return
971 return (bool) apply_filters( 'bbp_is_reply_pending', (bool) $reply_status, $reply_id );
972 }
973
974 /**
975 * Is the reply private?
976 *
977 * @since 2.6.0 bbPress (r5507)
978 *
979 * @param int $reply_id Optional. Topic id
980 * @return bool True if private, false if not.
981 */
982 function bbp_is_reply_private( $reply_id = 0 ) {
983 $reply_id = bbp_get_reply_id( $reply_id );
984 $status = bbp_get_private_status_id();
985 $reply_status = bbp_get_reply_status( $reply_id ) === $status;
986
987 // Filter & return
988 return (bool) apply_filters( 'bbp_is_reply_private', (bool) $reply_status, $reply_id );
989 }
990
991 /**
992 * Is the reply by an anonymous user?
993 *
994 * @since 2.0.0 bbPress (r2753)
995 *
996 * @param int $reply_id Optional. Reply id
997 * @return bool True if the post is by an anonymous user, false if not.
998 */
999 function bbp_is_reply_anonymous( $reply_id = 0 ) {
1000 $reply_id = bbp_get_reply_id( $reply_id );
1001 $retval = false;
1002
1003 if ( ! bbp_get_reply_author_id( $reply_id ) ) {
1004 $retval = true;
1005
1006 } elseif ( get_post_meta( $reply_id, '_bbp_anonymous_name', true ) ) {
1007 $retval = true;
1008
1009 } elseif ( get_post_meta( $reply_id, '_bbp_anonymous_email', true ) ) {
1010 $retval = true;
1011 }
1012
1013 // Filter & return
1014 return (bool) apply_filters( 'bbp_is_reply_anonymous', $retval, $reply_id );
1015 }
1016
1017 /**
1018 * Deprecated. Use bbp_reply_author_display_name() instead.
1019 *
1020 * Output the author of the reply
1021 *
1022 * @since 2.0.0 bbPress (r2667)
1023 *
1024 * @deprecated 2.5.0 bbPress (r5119)
1025 *
1026 * @param int $reply_id Optional. Reply id
1027 */
1028 function bbp_reply_author( $reply_id = 0 ) {
1029 echo bbp_get_reply_author( $reply_id );
1030 }
1031 /**
1032 * Deprecated. Use bbp_get_reply_author_display_name() instead.
1033 *
1034 * Return the author of the reply
1035 *
1036 * @since 2.0.0 bbPress (r2667)
1037 *
1038 * @deprecated 2.5.0 bbPress (r5119)
1039 *
1040 * @param int $reply_id Optional. Reply id
1041 * @return string Author of reply
1042 */
1043 function bbp_get_reply_author( $reply_id = 0 ) {
1044 $reply_id = bbp_get_reply_id( $reply_id );
1045
1046 if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1047 $author = get_the_author_meta( 'display_name', bbp_get_reply_author_id( $reply_id ) );
1048 } else {
1049 $author = get_post_meta( $reply_id, '_bbp_anonymous_name', true );
1050 }
1051
1052 // Filter & return
1053 return apply_filters( 'bbp_get_reply_author', $author, $reply_id );
1054 }
1055
1056 /**
1057 * Output the author ID of the reply
1058 *
1059 * @since 2.0.0 bbPress (r2667)
1060 *
1061 * @param int $reply_id Optional. Reply id
1062 */
1063 function bbp_reply_author_id( $reply_id = 0 ) {
1064 echo bbp_get_reply_author_id( $reply_id );
1065 }
1066 /**
1067 * Return the author ID of the reply
1068 *
1069 * @since 2.0.0 bbPress (r2667)
1070 *
1071 * @param int $reply_id Optional. Reply id
1072 * @return string Author id of reply
1073 */
1074 function bbp_get_reply_author_id( $reply_id = 0 ) {
1075 $reply_id = bbp_get_reply_id( $reply_id );
1076 $author_id = get_post_field( 'post_author', $reply_id );
1077
1078 // Filter & return
1079 return (int) apply_filters( 'bbp_get_reply_author_id', $author_id, $reply_id );
1080 }
1081
1082 /**
1083 * Output the author display_name of the reply
1084 *
1085 * @since 2.0.0 bbPress (r2667)
1086 *
1087 * @param int $reply_id Optional. Reply id
1088 */
1089 function bbp_reply_author_display_name( $reply_id = 0 ) {
1090 echo bbp_get_reply_author_display_name( $reply_id );
1091 }
1092 /**
1093 * Return the author display_name of the reply
1094 *
1095 * @since 2.0.0 bbPress (r2667)
1096 *
1097 * @param int $reply_id Optional. Reply id
1098 * @return string The display name of the author of the reply
1099 */
1100 function bbp_get_reply_author_display_name( $reply_id = 0 ) {
1101 $reply_id = bbp_get_reply_id( $reply_id );
1102
1103 // User is not a guest
1104 if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1105
1106 // Get the author ID
1107 $author_id = bbp_get_reply_author_id( $reply_id );
1108
1109 // Try to get a display name
1110 $author_name = get_the_author_meta( 'display_name', $author_id );
1111
1112 // Fall back to user login
1113 if ( empty( $author_name ) ) {
1114 $author_name = get_the_author_meta( 'user_login', $author_id );
1115 }
1116
1117 // User does not have an account
1118 } else {
1119 $author_name = get_post_meta( $reply_id, '_bbp_anonymous_name', true );
1120 }
1121
1122 // Fallback if nothing could be found
1123 if ( empty( $author_name ) ) {
1124 $author_name = bbp_get_fallback_display_name( $reply_id );
1125 }
1126
1127 // Filter & return
1128 return apply_filters( 'bbp_get_reply_author_display_name', $author_name, $reply_id );
1129 }
1130
1131 /**
1132 * Output the author avatar of the reply
1133 *
1134 * @since 2.0.0 bbPress (r2667)
1135 *
1136 * @param int $reply_id Optional. Reply id
1137 * @param int $size Optional. Size of the avatar. Defaults to 40
1138 */
1139 function bbp_reply_author_avatar( $reply_id = 0, $size = 40 ) {
1140 echo bbp_get_reply_author_avatar( $reply_id, $size );
1141 }
1142 /**
1143 * Return the author avatar of the reply
1144 *
1145 * @since 2.0.0 bbPress (r2667)
1146 *
1147 * @param int $reply_id Optional. Reply id
1148 * @param int $size Optional. Size of the avatar. Defaults to 40
1149 * @return string Avatar of author of the reply
1150 */
1151 function bbp_get_reply_author_avatar( $reply_id = 0, $size = 40 ) {
1152 $reply_id = bbp_get_reply_id( $reply_id );
1153 if ( ! empty( $reply_id ) ) {
1154 // Check for anonymous user
1155 if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1156 $author_avatar = get_avatar( bbp_get_reply_author_id( $reply_id ), $size );
1157 } else {
1158 $author_avatar = get_avatar( get_post_meta( $reply_id, '_bbp_anonymous_email', true ), $size );
1159 }
1160 } else {
1161 $author_avatar = '';
1162 }
1163
1164 // Filter & return
1165 return apply_filters( 'bbp_get_reply_author_avatar', $author_avatar, $reply_id, $size );
1166 }
1167
1168 /**
1169 * Output the author link of the reply
1170 *
1171 * @since 2.0.0 bbPress (r2717)
1172 *
1173 * @param array $args Optional. If it is an integer, it is used as reply id.
1174 */
1175 function bbp_reply_author_link( $args = array() ) {
1176 echo bbp_get_reply_author_link( $args );
1177 }
1178 /**
1179 * Return the author link of the reply
1180 *
1181 * @since 2.0.0 bbPress (r2717)
1182 *
1183 * @param array $args Optional. If an integer, it is used as reply id.
1184 * @return string Author link of reply
1185 */
1186 function bbp_get_reply_author_link( $args = array() ) {
1187
1188 // Parse arguments against default values
1189 $r = bbp_parse_args(
1190 $args,
1191 array(
1192 'post_id' => 0,
1193 'link_title' => '',
1194 'type' => 'both',
1195 'size' => 80,
1196 'sep' => '',
1197 'show_role' => false
1198 ),
1199 'get_reply_author_link'
1200 );
1201
1202 // Default return value
1203 $author_link = '';
1204
1205 // Used as reply_id
1206 $reply_id = is_numeric( $args )
1207 ? bbp_get_reply_id( $args )
1208 : bbp_get_reply_id( $r['post_id'] );
1209
1210 // Reply ID is good
1211 if ( ! empty( $reply_id ) ) {
1212
1213 // Get some useful reply information
1214 $author_url = bbp_get_reply_author_url( $reply_id );
1215 $anonymous = bbp_is_reply_anonymous( $reply_id );
1216
1217 // Tweak link title if empty
1218 if ( empty( $r['link_title'] ) ) {
1219 $author = bbp_get_reply_author_display_name( $reply_id );
1220 $title = empty( $anonymous )
1221 /* translators: %s: Author's display name */
1222 ? esc_attr__( "View %s's profile", 'bbpress' )
1223 /* translators: %s: Author's display name */
1224 : esc_attr__( "Visit %s's website", 'bbpress' );
1225
1226 $link_title = sprintf( $title, $author );
1227
1228 // Use what was passed if not
1229 } else {
1230 $link_title = $r['link_title'];
1231 }
1232
1233 // Setup title and author_links array
1234 $author_links = array();
1235 $link_title = ! empty( $link_title )
1236 ? ' title="' . esc_attr( $link_title ) . '"'
1237 : '';
1238
1239 // Get avatar (unescaped, because HTML)
1240 if ( ( 'avatar' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1241 $author_links['avatar'] = bbp_get_reply_author_avatar( $reply_id, $r['size'] );
1242 }
1243
1244 // Get display name (escaped, because never HTML)
1245 if ( ( 'name' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1246 $author_links['name'] = esc_html( bbp_get_reply_author_display_name( $reply_id ) );
1247 }
1248
1249 // Empty array
1250 $links = array();
1251 $sprint = '<span %1$s>%2$s</span>';
1252
1253 // Wrap each link
1254 foreach ( $author_links as $link => $link_text ) {
1255 $link_class = ' class="bbp-author-' . esc_attr( $link ) . '"';
1256 $links[] = sprintf( $sprint, $link_class, $link_text );
1257 }
1258
1259 // Juggle
1260 $author_links = $links;
1261 unset( $links );
1262
1263 // Filter sections
1264 $sections = apply_filters( 'bbp_get_reply_author_links', $author_links, $r, $args );
1265
1266 // Assemble sections into author link
1267 $author_link = implode( $r['sep'], $sections );
1268
1269 // Only wrap in link if profile exists
1270 if ( empty( $anonymous ) && bbp_user_has_profile( bbp_get_reply_author_id( $reply_id ) ) ) {
1271 $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 );
1272 }
1273
1274 // Role is not linked
1275 if ( true === $r['show_role'] ) {
1276 $author_link .= bbp_get_reply_author_role( array( 'reply_id' => $reply_id ) );
1277 }
1278 }
1279
1280 // Filter & return
1281 return apply_filters( 'bbp_get_reply_author_link', $author_link, $r, $args );
1282 }
1283
1284 /**
1285 * Output the author url of the reply
1286 *
1287 * @since 2.0.0 bbPress (r2667)
1288 *
1289 * @param int $reply_id Optional. Reply id
1290 */
1291 function bbp_reply_author_url( $reply_id = 0 ) {
1292 echo esc_url( bbp_get_reply_author_url( $reply_id ) );
1293 }
1294 /**
1295 * Return the author url of the reply
1296 *
1297 * @since 2.0.0 bbPress (r2667)
1298 *
1299 * @param int $reply_id Optional. Reply id
1300 * @return string Author URL of the reply
1301 */
1302 function bbp_get_reply_author_url( $reply_id = 0 ) {
1303 $reply_id = bbp_get_reply_id( $reply_id );
1304
1305 // Check for anonymous user or non-existant user
1306 if ( ! bbp_is_reply_anonymous( $reply_id ) && bbp_user_has_profile( bbp_get_reply_author_id( $reply_id ) ) ) {
1307 $author_url = bbp_get_user_profile_url( bbp_get_reply_author_id( $reply_id ) );
1308 } else {
1309 $author_url = get_post_meta( $reply_id, '_bbp_anonymous_website', true );
1310 if ( empty( $author_url ) ) {
1311 $author_url = '';
1312 }
1313 }
1314
1315 // Filter & return
1316 return apply_filters( 'bbp_get_reply_author_url', $author_url, $reply_id );
1317 }
1318
1319 /**
1320 * Output the reply author email address
1321 *
1322 * @since 2.0.0 bbPress (r3445)
1323 *
1324 * @param int $reply_id Optional. Reply id
1325 */
1326 function bbp_reply_author_email( $reply_id = 0 ) {
1327 echo bbp_get_reply_author_email( $reply_id );
1328 }
1329 /**
1330 * Return the reply author email address
1331 *
1332 * @since 2.0.0 bbPress (r3445)
1333 *
1334 * @param int $reply_id Optional. Reply id
1335 * @return string Reply author email address
1336 */
1337 function bbp_get_reply_author_email( $reply_id = 0 ) {
1338 $reply_id = bbp_get_reply_id( $reply_id );
1339
1340 // Not anonymous
1341 if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1342
1343 // Use reply author email address
1344 $user_id = bbp_get_reply_author_id( $reply_id );
1345 $user = get_userdata( $user_id );
1346 $author_email = ! empty( $user->user_email ) ? $user->user_email : '';
1347
1348 // Anonymous
1349 } else {
1350
1351 // Get email from post meta
1352 $author_email = get_post_meta( $reply_id, '_bbp_anonymous_email', true );
1353
1354 // Sanity check for missing email address
1355 if ( empty( $author_email ) ) {
1356 $author_email = '';
1357 }
1358 }
1359
1360 // Filter & return
1361 return apply_filters( 'bbp_get_reply_author_email', $author_email, $reply_id );
1362 }
1363
1364 /**
1365 * Output the reply author role
1366 *
1367 * @since 2.1.0 bbPress (r3860)
1368 *
1369 * @param array $args Optional.
1370 */
1371 function bbp_reply_author_role( $args = array() ) {
1372 echo bbp_get_reply_author_role( $args );
1373 }
1374 /**
1375 * Return the reply author role
1376 *
1377 * @since 2.1.0 bbPress (r3860)
1378 *
1379 * @param array $args Optional.
1380 * @return string Reply author role
1381 */
1382 function bbp_get_reply_author_role( $args = array() ) {
1383
1384 // Parse arguments against default values
1385 $r = bbp_parse_args(
1386 $args,
1387 array(
1388 'reply_id' => 0,
1389 'class' => false,
1390 'before' => '<div class="bbp-author-role">',
1391 'after' => '</div>'
1392 ),
1393 'get_reply_author_role'
1394 );
1395
1396 $reply_id = bbp_get_reply_id( $r['reply_id'] );
1397 $role = bbp_get_user_display_role( bbp_get_reply_author_id( $reply_id ) );
1398
1399 // Backwards compatibilty with old 'class' argument
1400 if ( ! empty( $r['class'] ) ) {
1401 $author_role = sprintf( '%1$s<div class="%2$s">%3$s</div>%4$s', $r['before'], esc_attr( $r['class'] ), esc_html( $role ), $r['after'] );
1402
1403 // Simpler before & after arguments
1404 // https://bbpress.trac.wordpress.org/ticket/2557
1405 } else {
1406 $author_role = $r['before'] . $role . $r['after'];
1407 }
1408
1409 // Filter & return
1410 return apply_filters( 'bbp_get_reply_author_role', $author_role, $r, $args );
1411 }
1412
1413 /**
1414 * Output the topic title a reply belongs to
1415 *
1416 * @since 2.0.0 bbPress (r2553)
1417 *
1418 * @param int $reply_id Optional. Reply id
1419 */
1420 function bbp_reply_topic_title( $reply_id = 0 ) {
1421 echo bbp_get_reply_topic_title( $reply_id );
1422 }
1423 /**
1424 * Return the topic title a reply belongs to
1425 *
1426 * @since 2.0.0 bbPress (r2553)
1427 *
1428 * @param int $reply_id Optional. Reply id
1429 * @return string The topic title of the reply
1430 */
1431 function bbp_get_reply_topic_title( $reply_id = 0 ) {
1432 $reply_id = bbp_get_reply_id( $reply_id );
1433 $topic_id = bbp_get_reply_topic_id( $reply_id );
1434
1435 // Filter & return
1436 return apply_filters( 'bbp_get_reply_topic_title', bbp_get_topic_title( $topic_id ), $reply_id );
1437 }
1438
1439 /**
1440 * Output the topic id a reply belongs to
1441 *
1442 * @since 2.0.0 bbPress (r2553)
1443 *
1444 * @param int $reply_id Optional. Reply id
1445 */
1446 function bbp_reply_topic_id( $reply_id = 0 ) {
1447 echo bbp_get_reply_topic_id( $reply_id );
1448 }
1449 /**
1450 * Return the topic id a reply belongs to
1451 *
1452 * @since 2.0.0 bbPress (r2553)
1453 *
1454 * @param int $reply_id Optional. Reply id
1455 * @return int The topic id of the reply
1456 */
1457 function bbp_get_reply_topic_id( $reply_id = 0 ) {
1458 $reply_id = bbp_get_reply_id( $reply_id );
1459 $topic_id = (int) get_post_field( 'post_parent', $reply_id );
1460
1461 // Meta-data fallback
1462 if ( empty( $topic_id ) ) {
1463 $topic_id = (int) get_post_meta( $reply_id, '_bbp_topic_id', true );
1464 }
1465
1466 // Filter
1467 if ( ! empty( $topic_id ) ) {
1468 $topic_id = (int) bbp_get_topic_id( $topic_id );
1469 }
1470
1471 // Filter & return
1472 return (int) apply_filters( 'bbp_get_reply_topic_id', $topic_id, $reply_id );
1473 }
1474
1475 /**
1476 * Output the forum id a reply belongs to
1477 *
1478 * @since 2.0.0 bbPress (r2679)
1479 *
1480 * @param int $reply_id Optional. Reply id
1481 */
1482 function bbp_reply_forum_id( $reply_id = 0 ) {
1483 echo bbp_get_reply_forum_id( $reply_id );
1484 }
1485 /**
1486 * Return the forum id a reply belongs to
1487 *
1488 * @since 2.0.0 bbPress (r2679)
1489 *
1490 * @param int $reply_id Optional. Reply id
1491 *
1492 * @return int The forum id of the reply
1493 */
1494 function bbp_get_reply_forum_id( $reply_id = 0 ) {
1495 $reply_id = bbp_get_reply_id( $reply_id );
1496 $topic_id = bbp_get_reply_topic_id( $reply_id );
1497 $forum_id = (int) get_post_field( 'post_parent', $topic_id );
1498
1499 // Meta-data fallback
1500 if ( empty( $forum_id ) ) {
1501 $forum_id = (int) get_post_meta( $reply_id, '_bbp_forum_id', true );
1502 }
1503
1504 // Filter
1505 if ( ! empty( $forum_id ) ) {
1506 $forum_id = (int) bbp_get_forum_id( $forum_id );
1507 }
1508
1509 // Filter & return
1510 return (int) apply_filters( 'bbp_get_reply_forum_id', $forum_id, $reply_id );
1511 }
1512
1513 /**
1514 * Output the ancestor reply id of a reply
1515 *
1516 * @since 2.4.0 bbPress (r4944)
1517 *
1518 * @param int $reply_id Optional. Reply id
1519 */
1520 function bbp_reply_ancestor_id( $reply_id = 0 ) {
1521 echo bbp_get_reply_ancestor_id( $reply_id );
1522 }
1523 /**
1524 * Return the ancestor reply id of a reply
1525 *
1526 * @since 2.4.0 bbPress (r4944)
1527 *
1528 * @param in $reply_id Reply id
1529 */
1530 function bbp_get_reply_ancestor_id( $reply_id = 0 ) {
1531
1532 // Validation
1533 $reply_id = bbp_get_reply_id( $reply_id );
1534 if ( empty( $reply_id ) ) {
1535 return false;
1536 }
1537
1538 // Find highest reply ancestor
1539 $ancestor_id = $reply_id;
1540 while ( $parent_id = bbp_get_reply_to( $ancestor_id ) ) {
1541 if ( empty( $parent_id ) || ( $parent_id === $ancestor_id ) || ( bbp_get_reply_topic_id( $reply_id ) === $parent_id ) || ( $parent_id === $reply_id ) ) {
1542 break;
1543 }
1544 $ancestor_id = $parent_id;
1545 }
1546
1547 return (int) $ancestor_id;
1548 }
1549
1550 /**
1551 * Output the reply to id of a reply
1552 *
1553 * @since 2.4.0 bbPress (r4944)
1554 *
1555 * @param int $reply_id Optional. Reply id
1556 */
1557 function bbp_reply_to( $reply_id = 0 ) {
1558 echo bbp_get_reply_to( $reply_id );
1559 }
1560 /**
1561 * Return the reply to id of a reply
1562 *
1563 * @since 2.4.0 bbPress (r4944)
1564 *
1565 * @param int $reply_id Optional. Reply id
1566 * @return int The parent reply id of the reply
1567 */
1568 function bbp_get_reply_to( $reply_id = 0 ) {
1569
1570 // Assume there is no reply_to set
1571 $reply_to = 0;
1572
1573 // Check that reply_id is valid
1574 $reply_id = bbp_get_reply_id( $reply_id );
1575
1576 // Get reply_to value
1577 if ( ! empty( $reply_id ) ) {
1578 $reply_to = (int) get_post_meta( $reply_id, '_bbp_reply_to', true );
1579 }
1580
1581 // Filter & return
1582 return (int) apply_filters( 'bbp_get_reply_to', $reply_to, $reply_id );
1583 }
1584
1585 /**
1586 * Output the link for the reply to
1587 *
1588 * @since 2.4.0 bbPress (r4944)
1589 *
1590 * @param array $args
1591 */
1592 function bbp_reply_to_link( $args = array() ) {
1593 echo bbp_get_reply_to_link( $args );
1594 }
1595
1596 /**
1597 * Return the link for a reply to a reply
1598 *
1599 * @since 2.4.0 bbPress (r4944)
1600 *
1601 * @param array $args Arguments
1602 * @return string Link for a reply to a reply
1603 */
1604 function bbp_get_reply_to_link( $args = array() ) {
1605
1606 // Parse arguments against default values
1607 $r = bbp_parse_args(
1608 $args,
1609 array(
1610 'id' => 0,
1611 'link_before' => '',
1612 'link_after' => '',
1613 'reply_text' => esc_html_x( 'Reply', 'verb', 'bbpress' ),
1614 'depth' => 0,
1615 'add_below' => 'post',
1616 'respond_id' => 'new-reply-' . bbp_get_topic_id(),
1617 ),
1618 'get_reply_to_link'
1619 );
1620
1621 // Get the reply to use it's ID and post_parent
1622 $reply = bbp_get_reply( $r['id'] );
1623 $topic_id = bbp_get_reply_topic_id( $reply->ID );
1624
1625 // Bail if no reply or user cannot reply
1626 if ( empty( $reply ) || empty( $topic_id ) || bbp_is_single_reply() || ! bbp_current_user_can_access_create_reply_form() ) {
1627 return;
1628 }
1629
1630 // Build the URI and return value
1631 $uri = bbp_get_reply_url( $reply->ID );
1632 $uri = strtok( $uri, '#' );
1633 $uri = add_query_arg( array( 'bbp_reply_to' => $reply->ID ), $uri );
1634 $uri = wp_nonce_url( $uri, 'respond_id_' . $reply->ID );
1635 $uri = $uri . '#new-post';
1636
1637 // Only add onclick if replies are threaded
1638 if ( bbp_thread_replies() ) {
1639
1640 // Array of classes to pass to moveForm
1641 $move_form = array(
1642 $r['add_below'] . '-' . $reply->ID,
1643 $reply->ID,
1644 $r['respond_id'],
1645 $reply->post_parent
1646 );
1647
1648 // Build the onclick
1649 $onclick = ' onclick="return addReply.moveForm(\'' . implode( "','", $move_form ) . '\');"';
1650
1651 // No onclick if replies are not threaded
1652 } else {
1653 $onclick = '';
1654 }
1655
1656 // Add $uri to the array, to be passed through the filter
1657 $r['uri'] = $uri;
1658 $retval = $r['link_before'] . '<a role="button" href="' . esc_url( $r['uri'] ) . '" class="bbp-reply-to-link"' . $onclick . '>' . $r['reply_text'] . '</a>' . $r['link_after'];
1659
1660 // Filter & return
1661 return apply_filters( 'bbp_get_reply_to_link', $retval, $r, $args );
1662 }
1663
1664 /**
1665 * Output the reply to a reply cancellation link
1666 *
1667 * @since 2.4.0 bbPress (r4944)
1668 */
1669 function bbp_cancel_reply_to_link( $text = '' ) {
1670 echo bbp_get_cancel_reply_to_link( $text );
1671 }
1672 /**
1673 * Return the cancellation link for a reply to a reply
1674 *
1675 * @since 2.4.0 bbPress (r4944)
1676 *
1677 * @param string $text The cancel text
1678 * @return string The cancellation link
1679 */
1680 function bbp_get_cancel_reply_to_link( $text = '' ) {
1681
1682 // Bail if not hierarchical or editing a reply
1683 if ( ! bbp_thread_replies() || bbp_is_reply_edit() ) {
1684 return;
1685 }
1686
1687 // Set default text
1688 if ( empty( $text ) ) {
1689 $text = esc_html__( 'Cancel', 'bbpress' );
1690 }
1691
1692 // Replying to...
1693 $reply_to = isset( $_GET['bbp_reply_to'] )
1694 ? (int) $_GET['bbp_reply_to']
1695 : 0;
1696
1697 // Set visibility
1698 $style = ! empty( $reply_to ) ? '' : ' style="display:none;"';
1699 $link = remove_query_arg( array( 'bbp_reply_to', '_wpnonce' ) ) . "#post-{$reply_to}";
1700 $retval = sprintf( '<a href="%1$s" id="bbp-cancel-reply-to-link"%2$s>%3$s</a>', esc_url( $link ), $style, esc_html( $text ) );
1701
1702 // Filter & return
1703 return apply_filters( 'bbp_get_cancel_reply_to_link', $retval, $link, $text );
1704 }
1705
1706 /**
1707 * Output the numeric position of a reply within a topic
1708 *
1709 * @since 2.0.0 bbPress (r2984)
1710 *
1711 * @param int $reply_id Optional. Reply id
1712 * @param int $topic_id Optional. Topic id
1713 */
1714 function bbp_reply_position( $reply_id = 0, $topic_id = 0 ) {
1715 echo bbp_get_reply_position( $reply_id, $topic_id );
1716 }
1717 /**
1718 * Return the numeric position of a reply within a topic
1719 *
1720 * @since 2.0.0 bbPress (r2984)
1721 *
1722 * @param int $reply_id Optional. Reply id
1723 * @param int $topic_id Optional. Topic id
1724 * @return int Reply position
1725 */
1726 function bbp_get_reply_position( $reply_id = 0, $topic_id = 0 ) {
1727
1728 // Get required data
1729 $reply_id = bbp_get_reply_id( $reply_id );
1730 $reply_position = get_post_field( 'menu_order', $reply_id );
1731
1732 // Reply doesn't have a position so get the raw value
1733 if ( empty( $reply_position ) ) {
1734
1735 // Get topic ID
1736 $topic_id = ! empty( $topic_id )
1737 ? bbp_get_topic_id( $topic_id )
1738 : bbp_get_reply_topic_id( $reply_id );
1739
1740 // Post is not the topic
1741 if ( $reply_id !== $topic_id ) {
1742 $reply_position = bbp_get_reply_position_raw( $reply_id, $topic_id );
1743
1744 // Update the reply position in the posts table so we'll never have
1745 // to hit the DB again.
1746 if ( ! empty( $reply_position ) ) {
1747 bbp_update_reply_position( $reply_id, $reply_position );
1748 }
1749
1750 // Topic's position is always 0
1751 } else {
1752 $reply_position = 0;
1753 }
1754 }
1755
1756 // Bump the position by one if the topic is included in the reply loop
1757 if ( ! bbp_show_lead_topic() ) {
1758 $reply_position++;
1759 }
1760
1761 // Filter & return
1762 return (int) apply_filters( 'bbp_get_reply_position', $reply_position, $reply_id, $topic_id );
1763 }
1764
1765 /** Reply Admin Links *********************************************************/
1766
1767 /**
1768 * Output admin links for reply
1769 *
1770 * @since 2.0.0 bbPress (r2667)
1771 *
1772 * @param array $args See {@link bbp_get_reply_admin_links()}
1773 */
1774 function bbp_reply_admin_links( $args = array() ) {
1775 echo bbp_get_reply_admin_links( $args );
1776 }
1777 /**
1778 * Return admin links for reply
1779 *
1780 * @since 2.0.0 bbPress (r2667)
1781 *
1782 * @param array $args This function supports these arguments:
1783 * - id: Optional. Reply id
1784 * - before: HTML before the links. Defaults to
1785 * '<span class="bbp-admin-links">'
1786 * - after: HTML after the links. Defaults to '</span>'
1787 * - sep: Separator. Defaults to ' | '
1788 * - links: Array of the links to display. By default, edit, trash,
1789 * spam, reply move, and topic split links are displayed
1790 * @return string Reply admin links
1791 */
1792 function bbp_get_reply_admin_links( $args = array() ) {
1793
1794 // Parse arguments against default values
1795 $r = bbp_parse_args(
1796 $args,
1797 array(
1798 'id' => 0,
1799 'before' => '<span class="bbp-admin-links">',
1800 'after' => '</span>',
1801 'sep' => ' | ',
1802 'links' => array()
1803 ),
1804 'get_reply_admin_links'
1805 );
1806
1807 $r['id'] = bbp_get_reply_id( $r['id'] );
1808
1809 // If post is a topic, return the topic admin links instead
1810 if ( bbp_is_topic( $r['id'] ) ) {
1811 return bbp_get_topic_admin_links( $args );
1812 }
1813
1814 // If post is not a reply, return
1815 if ( ! bbp_is_reply( $r['id'] ) ) {
1816 return;
1817 }
1818
1819 // If topic is trashed, do not show admin links
1820 if ( bbp_is_topic_trash( bbp_get_reply_topic_id( $r['id'] ) ) ) {
1821 return;
1822 }
1823
1824 // If no links were passed, default to the standard
1825 if ( empty( $r['links'] ) ) {
1826 $r['links'] = apply_filters(
1827 'bbp_reply_admin_links',
1828 array(
1829 'edit' => bbp_get_reply_edit_link ( $r ),
1830 'move' => bbp_get_reply_move_link ( $r ),
1831 'split' => bbp_get_topic_split_link ( $r ),
1832 'trash' => bbp_get_reply_trash_link ( $r ),
1833 'spam' => bbp_get_reply_spam_link ( $r ),
1834 'approve' => bbp_get_reply_approve_link( $r ),
1835 'reply' => bbp_get_reply_to_link ( $r )
1836 ),
1837 $r['id']
1838 );
1839 }
1840
1841 // See if links need to be unset
1842 $reply_status = bbp_get_reply_status( $r['id'] );
1843 if ( bbp_get_spam_status_id() === $reply_status ) {
1844
1845 // Trash link should not be visible on spam replies
1846 unset( $r['links']['trash'] );
1847 }
1848
1849 // Process the admin links
1850 $links = implode( $r['sep'], array_filter( $r['links'] ) );
1851 $retval = $r['before'] . $links . $r['after'];
1852
1853 // Filter & return
1854 return apply_filters( 'bbp_get_reply_admin_links', $retval, $r, $args );
1855 }
1856
1857 /**
1858 * Output the edit link of the reply
1859 *
1860 * @since 2.0.0 bbPress (r2740)
1861 *
1862 * @param array $args See {@link bbp_get_reply_edit_link()}
1863 */
1864 function bbp_reply_edit_link( $args = array() ) {
1865 echo bbp_get_reply_edit_link( $args );
1866 }
1867
1868 /**
1869 * Return the edit link of the reply
1870 *
1871 * @since 2.0.0 bbPress (r2740)
1872 *
1873 * @param array $args This function supports these arguments:
1874 * - id: Reply id
1875 * - link_before: HTML before the link
1876 * - link_after: HTML after the link
1877 * - edit_text: Edit text. Defaults to 'Edit'
1878 * @return string Reply edit link
1879 */
1880 function bbp_get_reply_edit_link( $args = array() ) {
1881
1882 // Parse arguments against default values
1883 $r = bbp_parse_args(
1884 $args,
1885 array(
1886 'id' => 0,
1887 'link_before' => '',
1888 'link_after' => '',
1889 'edit_text' => esc_html__( 'Edit', 'bbpress' )
1890 ),
1891 'get_reply_edit_link'
1892 );
1893
1894 // Get reply
1895 $reply = bbp_get_reply( $r['id'] );
1896
1897 // Bypass check if user has caps
1898 if ( ! current_user_can( 'edit_others_replies' ) ) {
1899
1900 // User cannot edit or it is past the lock time
1901 if ( empty( $reply ) || ! current_user_can( 'edit_reply', $reply->ID ) || bbp_past_edit_lock( $reply->post_date_gmt ) ) {
1902 return;
1903 }
1904 }
1905
1906 // Get uri
1907 $uri = bbp_get_reply_edit_url( $r['id'] );
1908
1909 // Bail if no uri
1910 if ( empty( $uri ) ) {
1911 return;
1912 }
1913
1914 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-edit-link">' . $r['edit_text'] . '</a>' . $r['link_after'];
1915
1916 // Filter & return
1917 return apply_filters( 'bbp_get_reply_edit_link', $retval, $r, $args );
1918 }
1919
1920 /**
1921 * Output URL to the reply edit page
1922 *
1923 * @since 2.0.0 bbPress (r2753)
1924 *
1925 * @param int $reply_id Optional. Reply id
1926 */
1927 function bbp_reply_edit_url( $reply_id = 0 ) {
1928 echo esc_url( bbp_get_reply_edit_url( $reply_id ) );
1929 }
1930 /**
1931 * Return URL to the reply edit page
1932 *
1933 * @since 2.0.0 bbPress (r2753)
1934 *
1935 * @param int $reply_id Optional. Reply id
1936 * @return string Reply edit url
1937 */
1938 function bbp_get_reply_edit_url( $reply_id = 0 ) {
1939
1940 // Bail if no reply
1941 $reply = bbp_get_reply( $reply_id );
1942 if ( empty( $reply ) ) {
1943 return;
1944 }
1945
1946 $reply_link = bbp_remove_view_all( bbp_get_reply_permalink( $reply_id ) );
1947
1948 // Pretty permalinks, previously used `bbp_use_pretty_urls()`
1949 // https://bbpress.trac.wordpress.org/ticket/3054
1950 if ( false === strpos( $reply_link, '?' ) ) {
1951 $url = trailingslashit( $reply_link ) . bbp_get_edit_slug();
1952 $url = user_trailingslashit( $url );
1953
1954 // Unpretty permalinks
1955 } else {
1956 $url = add_query_arg(
1957 array(
1958 bbp_get_reply_post_type() => $reply->post_name,
1959 bbp_get_edit_rewrite_id() => '1'
1960 ),
1961 $reply_link
1962 );
1963 }
1964
1965 // Maybe add view all
1966 $url = bbp_add_view_all( $url );
1967
1968 // Filter & return
1969 return apply_filters( 'bbp_get_reply_edit_url', $url, $reply_id );
1970 }
1971
1972 /**
1973 * Output the trash link of the reply
1974 *
1975 * @since 2.0.0 bbPress (r2740)
1976 *
1977 * @param array $args See {@link bbp_get_reply_trash_link()}
1978 */
1979 function bbp_reply_trash_link( $args = array() ) {
1980 echo bbp_get_reply_trash_link( $args );
1981 }
1982
1983 /**
1984 * Return the trash link of the reply
1985 *
1986 * @since 2.0.0 bbPress (r2740)
1987 *
1988 * @param array $args This function supports these arguments:
1989 * - id: Reply id
1990 * - link_before: HTML before the link
1991 * - link_after: HTML after the link
1992 * - sep: Separator
1993 * - trash_text: Trash text
1994 * - restore_text: Restore text
1995 * - delete_text: Delete text
1996 * @return string Reply trash link
1997 */
1998 function bbp_get_reply_trash_link( $args = array() ) {
1999
2000 // Parse arguments against default values
2001 $r = bbp_parse_args(
2002 $args,
2003 array(
2004 'id' => 0,
2005 'link_before' => '',
2006 'link_after' => '',
2007 'sep' => ' | ',
2008 'trash_text' => esc_html__( 'Trash', 'bbpress' ),
2009 'restore_text' => esc_html__( 'Restore', 'bbpress' ),
2010 'delete_text' => esc_html__( 'Delete', 'bbpress' )
2011 ),
2012 'get_reply_trash_link'
2013 );
2014
2015 // Get reply
2016 $reply = bbp_get_reply( $r['id'] );
2017
2018 // Bail if no reply or current user cannot delete
2019 if ( empty( $reply ) || ! current_user_can( 'delete_reply', $reply->ID ) ) {
2020 return;
2021 }
2022
2023 $actions = array();
2024 $trash_days = bbp_get_trash_days( bbp_get_reply_post_type() );
2025
2026 // Trashed
2027 if ( bbp_is_reply_trash( $reply->ID ) ) {
2028 $query = array(
2029 'action' => 'bbp_toggle_reply_trash',
2030 'sub_action' => 'untrash',
2031 'reply_id' => $reply->ID
2032 );
2033 $actions['untrash'] = '<a title="' . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( $query ), 'untrash-' . $reply->post_type . '_' . $reply->ID ) ) . '" class="bbp-reply-restore-link">' . $r['restore_text'] . '</a>';
2034
2035 // Trash
2036 } elseif ( ! empty( $trash_days ) ) {
2037 $query = array(
2038 'action' => 'bbp_toggle_reply_trash',
2039 'sub_action' => 'trash',
2040 'reply_id' => $reply->ID
2041 );
2042 $actions['trash'] = '<a title="' . esc_attr__( 'Move this item to the Trash', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( $query ), 'trash-' . $reply->post_type . '_' . $reply->ID ) ) . '" class="bbp-reply-trash-link">' . $r['trash_text'] . '</a>';
2043 }
2044
2045 // No trash
2046 if ( bbp_is_reply_trash( $reply->ID ) || empty( $trash_days ) ) {
2047 $query = array(
2048 'action' => 'bbp_toggle_reply_trash',
2049 'sub_action' => 'delete',
2050 'reply_id' => $reply->ID
2051 );
2052 $actions['delete'] = '<a title="' . esc_attr__( 'Delete this item permanently', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( $query ), 'delete-' . $reply->post_type . '_' . $reply->ID ) ) . '" onclick="return confirm(\'' . esc_js( __( 'Are you sure you want to delete that permanently?', 'bbpress' ) ) . '\' );" class="bbp-reply-delete-link">' . $r['delete_text'] . '</a>';
2053 }
2054
2055 // Process the admin links
2056 $retval = $r['link_before'] . implode( $r['sep'], $actions ) . $r['link_after'];
2057
2058 // Filter & return
2059 return apply_filters( 'bbp_get_reply_trash_link', $retval, $r, $args );
2060 }
2061
2062 /**
2063 * Output the spam link of the reply
2064 *
2065 * @since 2.0.0 bbPress (r2740)
2066 *
2067 * @param array $args See {@link bbp_get_reply_spam_link()}
2068 */
2069 function bbp_reply_spam_link( $args = array() ) {
2070 echo bbp_get_reply_spam_link( $args );
2071 }
2072
2073 /**
2074 * Return the spam link of the reply
2075 *
2076 * @since 2.0.0 bbPress (r2740)
2077 *
2078 * @param array $args This function supports these arguments:
2079 * - id: Reply id
2080 * - link_before: HTML before the link
2081 * - link_after: HTML after the link
2082 * - spam_text: Spam text
2083 * - unspam_text: Unspam text
2084 * @return string Reply spam link
2085 */
2086 function bbp_get_reply_spam_link( $args = array() ) {
2087
2088 // Parse arguments against default values
2089 $r = bbp_parse_args(
2090 $args,
2091 array(
2092 'id' => 0,
2093 'link_before' => '',
2094 'link_after' => '',
2095 'spam_text' => esc_html__( 'Spam', 'bbpress' ),
2096 'unspam_text' => esc_html__( 'Unspam', 'bbpress' )
2097 ),
2098 'get_reply_spam_link'
2099 );
2100
2101 // Get reply
2102 $reply = bbp_get_reply( $r['id'] );
2103
2104 // Bail if no reply or current user cannot moderate
2105 if ( empty( $reply ) || ! current_user_can( 'moderate', $reply->ID ) ) {
2106 return;
2107 }
2108
2109 $display = bbp_is_reply_spam( $reply->ID )
2110 ? $r['unspam_text']
2111 : $r['spam_text'];
2112
2113 $query = array(
2114 'action' => 'bbp_toggle_reply_spam',
2115 'reply_id' => $reply->ID
2116 );
2117
2118 $uri = add_query_arg( $query );
2119 $uri = wp_nonce_url( $uri, 'spam-reply_' . $reply->ID );
2120 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-spam-link">' . $display . '</a>' . $r['link_after'];
2121
2122 // Filter & return
2123 return apply_filters( 'bbp_get_reply_spam_link', $retval, $r, $args );
2124 }
2125
2126 /**
2127 * Move reply link
2128 *
2129 * Output the move link of the reply
2130 *
2131 * @since 2.3.0 bbPress (r4521)
2132 *
2133 * @param array $args See {@link bbp_get_reply_move_link()}
2134 */
2135 function bbp_reply_move_link( $args = array() ) {
2136 echo bbp_get_reply_move_link( $args );
2137 }
2138
2139 /**
2140 * Get move reply link
2141 *
2142 * Return the move link of the reply
2143 *
2144 * @since 2.3.0 bbPress (r4521)
2145 *
2146 * @param array $args This function supports these arguments:
2147 * - id: Reply id
2148 * - link_before: HTML before the link
2149 * - link_after: HTML after the link
2150 * - move_text: Move text
2151 * - move_title: Move title attribute
2152 * @return string Reply move link
2153 */
2154 function bbp_get_reply_move_link( $args = array() ) {
2155
2156 // Parse arguments against default values
2157 $r = bbp_parse_args(
2158 $args,
2159 array(
2160 'id' => 0,
2161 'link_before' => '',
2162 'link_after' => '',
2163 'split_text' => esc_html__( 'Move', 'bbpress' ),
2164 'split_title' => esc_attr__( 'Move this reply', 'bbpress' )
2165 ),
2166 'get_reply_move_link'
2167 );
2168
2169 // Get IDs
2170 $reply_id = bbp_get_reply_id( $r['id'] );
2171 $topic_id = bbp_get_reply_topic_id( $reply_id );
2172
2173 // Bail if no reply ID or user cannot moderate
2174 if ( empty( $reply_id ) || ! current_user_can( 'moderate', $topic_id ) ) {
2175 return;
2176 }
2177
2178 $uri = add_query_arg(
2179 array(
2180 'action' => 'move',
2181 'reply_id' => $reply_id
2182 ),
2183 bbp_get_reply_edit_url( $reply_id )
2184 );
2185
2186 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" title="' . $r['split_title'] . '" class="bbp-reply-move-link">' . $r['split_text'] . '</a>' . $r['link_after'];
2187
2188 // Filter & return
2189 return apply_filters( 'bbp_get_reply_move_link', $retval, $r, $args );
2190 }
2191
2192 /**
2193 * Split topic link
2194 *
2195 * Output the split link of the topic (but is bundled with each reply)
2196 *
2197 * @since 2.0.0 bbPress (r2756)
2198 *
2199 * @param array $args See {@link bbp_get_topic_split_link()}
2200 */
2201 function bbp_topic_split_link( $args = array() ) {
2202 echo bbp_get_topic_split_link( $args );
2203 }
2204
2205 /**
2206 * Get split topic link
2207 *
2208 * Return the split link of the topic (but is bundled with each reply)
2209 *
2210 * @since 2.0.0 bbPress (r2756)
2211 *
2212 * @param array $args This function supports these arguments:
2213 * - id: Reply id
2214 * - link_before: HTML before the link
2215 * - link_after: HTML after the link
2216 * - split_text: Split text
2217 * - split_title: Split title attribute
2218 * @return string Topic split link
2219 */
2220 function bbp_get_topic_split_link( $args = array() ) {
2221
2222 // Parse arguments against default values
2223 $r = bbp_parse_args(
2224 $args,
2225 array(
2226 'id' => 0,
2227 'link_before' => '',
2228 'link_after' => '',
2229 'split_text' => esc_html__( 'Split', 'bbpress' ),
2230 'split_title' => esc_attr__( 'Split the topic from this reply', 'bbpress' )
2231 ),
2232 'get_topic_split_link'
2233 );
2234
2235 // Get IDs
2236 $reply_id = bbp_get_reply_id( $r['id'] );
2237 $topic_id = bbp_get_reply_topic_id( $reply_id );
2238
2239 // Bail if no reply/topic ID, or user cannot moderate
2240 if ( empty( $reply_id ) || empty( $topic_id ) || ! current_user_can( 'moderate', $topic_id ) ) {
2241 return;
2242 }
2243
2244 $uri = add_query_arg(
2245 array(
2246 'action' => 'split',
2247 'reply_id' => $reply_id
2248 ),
2249 bbp_get_topic_edit_url( $topic_id )
2250 );
2251
2252 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" title="' . $r['split_title'] . '" class="bbp-topic-split-link">' . $r['split_text'] . '</a>' . $r['link_after'];
2253
2254 // Filter & return
2255 return apply_filters( 'bbp_get_topic_split_link', $retval, $r, $args );
2256 }
2257
2258 /**
2259 * Output the approve link of the reply
2260 *
2261 * @since 2.6.0 bbPress (r5507)
2262 *
2263 * @param array $args See {@link bbp_get_reply_approve_link()}
2264 */
2265 function bbp_reply_approve_link( $args = array() ) {
2266 echo bbp_get_reply_approve_link( $args );
2267 }
2268
2269 /**
2270 * Return the approve link of the reply
2271 *
2272 * @since 2.6.0 bbPress (r5507)
2273 *
2274 * @param array $args This function supports these args:
2275 * - id: Optional. Reply id
2276 * - link_before: Before the link
2277 * - link_after: After the link
2278 * - sep: Separator between links
2279 * - approve_text: Approve text
2280 * - unapprove_text: Unapprove text
2281 * @return string Reply approve link
2282 */
2283 function bbp_get_reply_approve_link( $args = array() ) {
2284
2285 // Parse arguments against default values
2286 $r = bbp_parse_args(
2287 $args,
2288 array(
2289 'id' => 0,
2290 'link_before' => '',
2291 'link_after' => '',
2292 'sep' => ' | ',
2293 'approve_text' => _x( 'Approve', 'Pending Status', 'bbpress' ),
2294 'unapprove_text' => _x( 'Unapprove', 'Pending Status', 'bbpress' )
2295 ),
2296 'get_reply_approve_link'
2297 );
2298
2299 // Get reply
2300 $reply = bbp_get_reply( $r['id'] );
2301
2302 // Bail if no reply or current user cannot moderate
2303 if ( empty( $reply ) || ! current_user_can( 'moderate', $reply->ID ) ) {
2304 return;
2305 }
2306
2307 $display = bbp_is_reply_pending( $reply->ID )
2308 ? $r['approve_text']
2309 : $r['unapprove_text'];
2310
2311 $query = array(
2312 'action' => 'bbp_toggle_reply_approve',
2313 'reply_id' => $reply->ID
2314 );
2315
2316 $uri = add_query_arg( $query );
2317 $uri = wp_nonce_url( $uri, 'approve-reply_' . $reply->ID );
2318 $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-approve-link">' . $display . '</a>' . $r['link_after'];
2319
2320 // Filter & return
2321 return apply_filters( 'bbp_get_reply_approve_link', $retval, $r, $args );
2322 }
2323
2324 /**
2325 * Output the row class of a reply
2326 *
2327 * @since 2.0.0 bbPress (r2678)
2328 *
2329 * @param int $reply_id Optional. Reply ID
2330 * @param array Extra classes you can pass when calling this function
2331 */
2332 function bbp_reply_class( $reply_id = 0, $classes = array() ) {
2333 echo bbp_get_reply_class( $reply_id, $classes );
2334 }
2335 /**
2336 * Return the row class of a reply
2337 *
2338 * @since 2.0.0 bbPress (r2678)
2339 *
2340 * @param int $reply_id Optional. Reply ID
2341 * @param array Extra classes you can pass when calling this function
2342 * @return string Row class of the reply
2343 */
2344 function bbp_get_reply_class( $reply_id = 0, $classes = array() ) {
2345 $bbp = bbpress();
2346 $reply_id = bbp_get_reply_id( $reply_id );
2347 $topic_id = bbp_get_reply_topic_id( $reply_id );
2348 $forum_id = bbp_get_reply_forum_id( $reply_id );
2349 $author_id = bbp_get_reply_author_id( $reply_id );
2350 $reply_pos = bbp_get_reply_position( $reply_id, true );
2351 $classes = array_filter( (array) $classes );
2352 $count = isset( $bbp->reply_query->current_post )
2353 ? (int) $bbp->reply_query->current_post
2354 : 1;
2355
2356 // Stripes
2357 $even_odd = ( $count % 2 )
2358 ? 'even'
2359 : 'odd';
2360
2361 // Forum moderator replied to topic
2362 $forum_moderator = ( bbp_is_user_forum_moderator( $author_id, $forum_id ) === $author_id )
2363 ? 'forum-mod'
2364 : '';
2365
2366 // Topic author replied to others
2367 $topic_author = ( bbp_get_topic_author_id( $topic_id ) === $author_id )
2368 ? 'topic-author'
2369 : '';
2370
2371 // Get reply classes
2372 $reply_classes = array(
2373 'loop-item-' . $count,
2374 'user-id-' . $author_id,
2375 'bbp-parent-forum-' . $forum_id,
2376 'bbp-parent-topic-' . $topic_id,
2377 'bbp-reply-position-' . $reply_pos,
2378 $even_odd,
2379 $topic_author,
2380 $forum_moderator
2381 );
2382
2383 // Run the topic classes through the post-class filters, which also
2384 // handles the escaping of each individual class.
2385 $post_classes = get_post_class( array_merge( $classes, $reply_classes ), $reply_id );
2386
2387 // Filter
2388 $new_classes = apply_filters( 'bbp_get_reply_class', $post_classes, $reply_id, $classes );
2389
2390 // Return
2391 return 'class="' . implode( ' ', $new_classes ) . '"';
2392 }
2393
2394 /** Pagination ****************************************************************/
2395
2396 /**
2397 * Return the base URL used inside of pagination links
2398 *
2399 * @since 2.6.0 bbPress (r6679)
2400 *
2401 * @param int $topic_id
2402 * @return string
2403 */
2404 function bbp_get_replies_pagination_base( $topic_id = 0 ) {
2405
2406 // If pretty permalinks are enabled, make our pagination pretty
2407 if ( bbp_use_pretty_urls() && ! bbp_is_topic_pending( $topic_id ) ) {
2408
2409 // User's replies
2410 if ( bbp_is_single_user_replies() ) {
2411 $base = bbp_get_user_replies_created_url( bbp_get_displayed_user_id() );
2412
2413 // Root profile page
2414 } elseif ( bbp_is_single_user() ) {
2415 $base = bbp_get_user_profile_url( bbp_get_displayed_user_id() );
2416
2417 // Any single post (for shortcodes)
2418 } elseif ( is_singular() ) {
2419 $base = get_permalink();
2420
2421 // Single topic
2422 } else {
2423 $base = get_permalink( $topic_id );
2424 }
2425
2426 $base = trailingslashit( $base ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' );
2427
2428 // Unpretty permalinks
2429 } else {
2430 $base = add_query_arg( 'paged', '%#%' );
2431 }
2432
2433 // Filter & return
2434 return apply_filters( 'bbp_get_replies_pagination_base', $base, $topic_id );
2435 }
2436
2437 /**
2438 * Output the topic pagination count
2439 *
2440 * The results are unescaped by design, to allow them to be filtered freely via
2441 * the 'bbp_get_topic_pagination_count' filter.
2442 *
2443 * @since 2.0.0 bbPress (r2519)
2444 *
2445 */
2446 function bbp_topic_pagination_count() {
2447 echo bbp_get_topic_pagination_count();
2448 }
2449 /**
2450 * Return the topic pagination count
2451 *
2452 * @since 2.0.0 bbPress (r2519)
2453 *
2454 * @return string Topic pagination count
2455 */
2456 function bbp_get_topic_pagination_count() {
2457 $bbp = bbpress();
2458
2459 // Define local variable(s)
2460 $retstr = '';
2461
2462 // Set pagination values
2463 $count_int = intval( $bbp->reply_query->post_count );
2464 $total_int = intval( $bbp->reply_query->found_posts );
2465 $ppp_int = intval( $bbp->reply_query->posts_per_page );
2466 $start_int = intval( ( $bbp->reply_query->paged - 1 ) * $ppp_int ) + 1;
2467 $to_int = intval( ( $start_int + ( $ppp_int - 1 ) > $total_int )
2468 ? $total_int
2469 : $start_int + ( $ppp_int - 1 )
2470 );
2471
2472 // Format numbers for display
2473 $count_num = bbp_number_format( $count_int );
2474 $total_num = bbp_number_format( $total_int );
2475 $from_num = bbp_number_format( $start_int );
2476 $to_num = bbp_number_format( $to_int );
2477
2478 // We are threading replies
2479 if ( bbp_thread_replies() ) {
2480 $walker = new BBP_Walker_Reply();
2481 $threads = absint( $walker->get_number_of_root_elements( $bbp->reply_query->posts ) - 1 );
2482 /* translators: %s: Number of reply threads */
2483 $retstr = sprintf( _n( 'Viewing %1$s reply thread', 'Viewing %1$s reply threads', $threads, 'bbpress' ), bbp_number_format( $threads ) );
2484
2485 // We are not including the lead topic
2486 } elseif ( bbp_show_lead_topic() ) {
2487
2488 // Several replies in a topic with a single page
2489 if ( empty( $to_num ) ) {
2490 /* translators: %1$s: Number of replies */
2491 $retstr = sprintf( _n( 'Viewing %1$s reply', 'Viewing %1$s replies', $total_int, 'bbpress' ), $total_num );
2492
2493 // Several replies in a topic with several pages
2494 } else {
2495 /* translators: 1: Number of replies being viewed, 2: Starting reply number, 3: Ending reply number, 4: Total replies */
2496 $retstr = sprintf( _n( 'Viewing %2$s replies (of %4$s total)', 'Viewing %1$s replies - %2$s through %3$s (of %4$s total)', $count_int, 'bbpress' ), $count_num, $from_num, $to_num, $total_num ); //phpcs:ignore
2497 }
2498
2499 // We are including the lead topic
2500 // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
2501 } else {
2502
2503 // Several posts in a topic with a single page
2504 if ( empty( $to_num ) ) {
2505 /* translators: %1$s: Number of posts */
2506 $retstr = sprintf( _n( 'Viewing %1$s post', 'Viewing %1$s posts', $total_int, 'bbpress' ), $total_num );
2507
2508 // Several posts in a topic with several pages
2509 } else {
2510 /* translators: 1: Number of posts being viewed, 2: Starting post number, 3: Ending post number, 4: Total posts */
2511 $retstr = sprintf( _n( 'Viewing %2$s post (of %4$s total)', 'Viewing %1$s posts - %2$s through %3$s (of %4$s total)', $count_int, 'bbpress' ), $count_num, $from_num, $to_num, $total_num ); //phpcs:ignore
2512 }
2513 }
2514
2515 // Escape results of _n()
2516 $retstr = esc_html( $retstr );
2517
2518 // Filter & return
2519 return apply_filters( 'bbp_get_topic_pagination_count', $retstr );
2520 }
2521
2522 /**
2523 * Output topic pagination links
2524 *
2525 * @since 2.0.0 bbPress (r2519)
2526 */
2527 function bbp_topic_pagination_links() {
2528 echo bbp_get_topic_pagination_links();
2529 }
2530 /**
2531 * Return topic pagination links
2532 *
2533 * @since 2.0.0 bbPress (r2519)
2534 *
2535 * @return string Topic pagination links
2536 */
2537 function bbp_get_topic_pagination_links() {
2538 $bbp = bbpress();
2539
2540 if ( ! isset( $bbp->reply_query->pagination_links ) || empty( $bbp->reply_query->pagination_links ) ) {
2541 return false;
2542 }
2543
2544 // Filter & return
2545 return apply_filters( 'bbp_get_topic_pagination_links', $bbp->reply_query->pagination_links );
2546 }
2547
2548 /** Forms *********************************************************************/
2549
2550 /**
2551 * Output the value of reply content field
2552 *
2553 * @since 2.0.0 bbPress (r3130)
2554 */
2555 function bbp_form_reply_content() {
2556 echo bbp_get_form_reply_content();
2557 }
2558 /**
2559 * Return the value of reply content field
2560 *
2561 * @since 2.0.0 bbPress (r3130)
2562 *
2563 * @return string Value of reply content field
2564 */
2565 function bbp_get_form_reply_content() {
2566
2567 // Get _POST data
2568 if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_reply_content'] ) ) {
2569 $reply_content = wp_unslash( $_POST['bbp_reply_content'] );
2570
2571 // Get edit data
2572 } elseif ( bbp_is_reply_edit() ) {
2573 $reply_content = bbp_get_global_post_field( 'post_content', 'raw' );
2574
2575 // No data
2576 } else {
2577 $reply_content = '';
2578 }
2579
2580 // Filter & return
2581 return apply_filters( 'bbp_get_form_reply_content', $reply_content );
2582 }
2583
2584 /**
2585 * Output the value of the reply to field
2586 *
2587 * @since 2.4.0 bbPress (r4944)
2588 */
2589 function bbp_form_reply_to() {
2590 echo bbp_get_form_reply_to();
2591 }
2592
2593 /**
2594 * Return the value of reply to field
2595 *
2596 * @since 2.4.0 bbPress (r4944)
2597 *
2598 * @return string Value of reply to field
2599 */
2600 function bbp_get_form_reply_to() {
2601
2602 // Set initial value
2603 $reply_to = 0;
2604
2605 // Get $_REQUEST data
2606 if ( isset( $_REQUEST['bbp_reply_to'] ) ) {
2607 $reply_to = bbp_validate_reply_to( $_REQUEST['bbp_reply_to'] );
2608 }
2609
2610 // If empty, get from meta
2611 if ( empty( $reply_to ) ) {
2612 $reply_to = bbp_get_reply_to();
2613 }
2614
2615 // Filter & return
2616 return apply_filters( 'bbp_get_form_reply_to', $reply_to );
2617 }
2618
2619 /**
2620 * Output a select box allowing to pick which reply an existing hierarchical
2621 * reply belongs to.
2622 *
2623 * @since 2.6.0 bbPress (r5387)
2624 *
2625 * @param int $reply_id
2626 */
2627 function bbp_reply_to_dropdown( $reply_id = 0 ) {
2628 echo bbp_get_reply_to_dropdown( $reply_id );
2629 }
2630 /**
2631 * Return a select box allowing to pick which topic/reply a reply belongs.
2632 *
2633 * @since 2.6.0 bbPress (r5387)
2634 *
2635 * @param int $reply_id
2636 *
2637 * @return string The dropdown
2638 */
2639 function bbp_get_reply_to_dropdown( $reply_id = 0 ) {
2640
2641 // Validate the reply data
2642 $reply_id = bbp_get_reply_id( $reply_id );
2643 $reply_to = bbp_get_reply_to( $reply_id );
2644 $topic_id = bbp_get_reply_topic_id( $reply_id );
2645
2646 // Get the replies
2647 $posts = get_posts(
2648 array(
2649 'post_type' => bbp_get_reply_post_type(),
2650 'post_status' => bbp_get_public_status_id(),
2651 'post_parent' => $topic_id,
2652 'numberposts' => -1,
2653 'orderby' => 'menu_order',
2654 'order' => 'ASC',
2655 )
2656 );
2657
2658 // Append `reply_to` for each reply so it can be walked
2659 foreach ( $posts as &$post ) {
2660
2661 // Check for reply post type
2662 $_reply_to = bbp_get_reply_to( $post->ID );
2663
2664 // Make sure it's a reply to a reply
2665 if ( empty( $_reply_to ) || ( $topic_id === $_reply_to ) ) {
2666 $_reply_to = 0;
2667 }
2668
2669 // Add reply_to to the post object so we can walk it later
2670 $post->reply_to = $_reply_to;
2671 }
2672
2673 // Default "None" text
2674 $show_none = ( 0 === $reply_id )
2675 ? esc_attr_x( 'None', 'Default reply to dropdown text', 'bbpress' )
2676 /* translators: 1: Topic ID, 2: Topic title */
2677 : sprintf( esc_attr__( '%1$s - %2$s', 'bbpress' ), $topic_id, bbp_get_topic_title( $topic_id ) );
2678
2679 // Get the dropdown and return it
2680 $retval = bbp_get_dropdown(
2681 array(
2682 'show_none' => $show_none,
2683 'select_id' => 'bbp_reply_to',
2684 'select_class' => 'bbp_dropdown',
2685 'exclude' => $reply_id,
2686 'selected' => $reply_to,
2687 'post_parent' => $topic_id,
2688 'post_type' => bbp_get_reply_post_type(),
2689 'max_depth' => bbp_thread_replies_depth(),
2690 'page' => 1,
2691 'per_page' => -1,
2692 'walker' => new BBP_Walker_Reply_Dropdown(),
2693 'posts' => $posts
2694 )
2695 );
2696
2697 // Filter & return
2698 return apply_filters( 'bbp_get_reply_to_dropdown', $retval, $reply_id, $reply_to, $topic_id );
2699 }
2700
2701 /**
2702 * Output checked value of reply log edit field
2703 *
2704 * @since 2.0.0 bbPress (r3130)
2705 */
2706 function bbp_form_reply_log_edit() {
2707 echo bbp_get_form_reply_log_edit();
2708 }
2709 /**
2710 * Return checked value of reply log edit field
2711 *
2712 * @since 2.0.0 bbPress (r3130)
2713 *
2714 * @return string Reply log edit checked value
2715 */
2716 function bbp_get_form_reply_log_edit() {
2717
2718 // Get _POST data
2719 if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_log_reply_edit'] ) ) {
2720 $reply_revision = (bool) $_POST['bbp_log_reply_edit'];
2721
2722 // No data
2723 } else {
2724 $reply_revision = true;
2725 }
2726
2727 // Get checked output
2728 $checked = checked( $reply_revision, true, false );
2729
2730 // Filter & return
2731 return apply_filters( 'bbp_get_form_reply_log_edit', $checked, $reply_revision );
2732 }
2733
2734 /**
2735 * Output the value of the reply edit reason
2736 *
2737 * @since 2.0.0 bbPress (r3130)
2738 */
2739 function bbp_form_reply_edit_reason() {
2740 echo bbp_get_form_reply_edit_reason();
2741 }
2742 /**
2743 * Return the value of the reply edit reason
2744 *
2745 * @since 2.0.0 bbPress (r3130)
2746 *
2747 * @return string Reply edit reason value
2748 */
2749 function bbp_get_form_reply_edit_reason() {
2750
2751 // Get _POST data
2752 if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_reply_edit_reason'] ) ) {
2753 $reply_edit_reason = wp_unslash( $_POST['bbp_reply_edit_reason'] );
2754
2755 // No data
2756 } else {
2757 $reply_edit_reason = '';
2758 }
2759
2760 // Filter & return
2761 return apply_filters( 'bbp_get_form_reply_edit_reason', $reply_edit_reason );
2762 }
2763
2764 /**
2765 * Output value reply status dropdown
2766 *
2767 * @since 2.6.0 bbPress (r5399)
2768 *
2769 * @param $args This function supports these arguments:
2770 * - select_id: Select id. Defaults to bbp_reply_status
2771 * - tab: Deprecated. Tabindex
2772 * - reply_id: Reply id
2773 * - selected: Override the selected option
2774 */
2775 function bbp_form_reply_status_dropdown( $args = array() ) {
2776 echo bbp_get_form_reply_status_dropdown( $args );
2777 }
2778 /**
2779 * Returns reply status dropdown
2780 *
2781 * This dropdown is only intended to be seen by users with the 'moderate'
2782 * capability. Because of this, no additional capability checks are performed
2783 * within this function to check available reply statuses.
2784 *
2785 * @since 2.6.0 bbPress (r5399)
2786 *
2787 * @param $args This function supports these arguments:
2788 * - select_id: Select id. Defaults to bbp_reply_status
2789 * - tab: Deprecated. Tabindex
2790 * - reply_id: Reply id
2791 * - selected: Override the selected option
2792 */
2793 function bbp_get_form_reply_status_dropdown( $args = array() ) {
2794
2795 // Parse arguments against default values
2796 $r = bbp_parse_args(
2797 $args,
2798 array(
2799 'select_id' => 'bbp_reply_status',
2800 'select_class' => 'bbp_dropdown',
2801 'tab' => false,
2802 'reply_id' => 0,
2803 'selected' => false
2804 ),
2805 'reply_status_dropdown'
2806 );
2807
2808 // No specific selected value passed
2809 if ( empty( $r['selected'] ) ) {
2810
2811 // Post value is passed
2812 if ( bbp_is_reply_form_post_request() && isset( $_POST[ $r['select_id'] ] ) ) {
2813 $r['selected'] = sanitize_key( $_POST[ $r['select_id'] ] );
2814
2815 // Edit reply
2816 } elseif ( bbp_is_reply_edit() ) {
2817 $r['reply_id'] = bbp_get_reply_id( $r['reply_id'] );
2818 $r['selected'] = bbp_get_reply_status( $r['reply_id'] );
2819
2820 // New reply
2821 } else {
2822 $r['selected'] = bbp_get_public_status_id();
2823 }
2824 }
2825
2826 // Start an output buffer, we'll finish it after the select loop
2827 ob_start(); ?>
2828
2829 <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'] ); ?>>
2830
2831 <?php foreach ( bbp_get_reply_statuses( $r['reply_id'] ) as $key => $label ) : ?>
2832
2833 <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $r['selected'] ); ?>><?php echo esc_html( $label ); ?></option>
2834
2835 <?php endforeach; ?>
2836
2837 </select>
2838
2839 <?php
2840
2841 // Filter & return
2842 return apply_filters( 'bbp_get_form_reply_status_dropdown', ob_get_clean(), $r, $args );
2843 }
2844
2845 /**
2846 * Verify if a POST request came from a failed reply attempt.
2847 *
2848 * Used to avoid cross-site request forgeries when checking posted reply form
2849 * content.
2850 *
2851 * @see bbp_reply_form_fields()
2852 *
2853 * @since 2.6.0 bbPress (r5558)
2854 *
2855 * @return boolean True if is a post request with valid nonce
2856 */
2857 function bbp_is_reply_form_post_request() {
2858
2859 // Bail if not a post request
2860 if ( ! bbp_is_post_request() ) {
2861 return false;
2862 }
2863
2864 // Creating a new reply
2865 if ( bbp_verify_nonce_request( 'bbp-new-reply' ) ) {
2866 return true;
2867 }
2868
2869 // Editing an existing reply
2870 if ( bbp_verify_nonce_request( 'bbp-edit-reply' ) ) {
2871 return true;
2872 }
2873
2874 return false;
2875 }
2876