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

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

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