PluginProbe
bbPress / 2.0-rc-3
bbPress v2.0-rc-3
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 / bbp-includes / bbp-common-functions.php

bbp-common-functions.php in bbPress 2.0-rc-3, at bbp-includes/bbp-common-functions.php

1,402 lines 45.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * bbPress Common Functions
5 *
6 * @package bbPress
7 * @subpackage Functions
8 */
9
10 // Exit if accessed directly
11 if ( !defined( 'ABSPATH' ) ) exit;
12
13 /** Post Meta *****************************************************************/
14
15 /**
16 * Update a posts forum meta ID
17 *
18 * @since bbPress (r3181)
19 *
20 * @param int $post_id The post to update
21 * @param int $forum_id The forum
22 */
23 function bbp_update_forum_id( $post_id, $forum_id ) {
24
25 // Allow the forum ID to be updated 'just in time' before save
26 $forum_id = apply_filters( 'bbp_update_forum_id', $forum_id, $post_id );
27
28 // Update the post meta forum ID
29 update_post_meta( $post_id, '_bbp_forum_id', (int) $forum_id );
30 }
31
32 /**
33 * Update a posts topic meta ID
34 *
35 * @since bbPress (r3181)
36 *
37 * @param int $post_id The post to update
38 * @param int $forum_id The forum
39 */
40 function bbp_update_topic_id( $post_id, $topic_id ) {
41
42 // Allow the topic ID to be updated 'just in time' before save
43 $topic_id = apply_filters( 'bbp_update_topic_id', $topic_id, $post_id );
44
45 // Update the post meta topic ID
46 update_post_meta( $post_id, '_bbp_topic_id', (int) $topic_id );
47 }
48
49 /**
50 * Update a posts reply meta ID
51 *
52 * @since bbPress (r3181)
53 *
54 * @param int $post_id The post to update
55 * @param int $forum_id The forum
56 */
57 function bbp_update_reply_id( $post_id, $reply_id ) {
58
59 // Allow the reply ID to be updated 'just in time' before save
60 $reply_id = apply_filters( 'bbp_update_reply_id', $reply_id, $post_id );
61
62 // Update the post meta reply ID
63 update_post_meta( $post_id, '_bbp_reply_id',(int) $reply_id );
64 }
65
66 /** Formatting ****************************************************************/
67
68 /**
69 * A bbPress specific method of formatting numeric values
70 *
71 * @since bbPress (r2486)
72 *
73 * @param string $number Number to format
74 * @param string $decimals Optional. Display decimals
75 * @uses apply_filters() Calls 'bbp_number_format' with the formatted values,
76 * number and display decimals bool
77 * @return string Formatted string
78 */
79 function bbp_number_format( $number, $decimals = false ) {
80
81 // If empty, set $number to '0'
82 if ( empty( $number ) || !is_numeric( $number ) )
83 $number = '0';
84
85 return apply_filters( 'bbp_number_format', number_format( $number, $decimals ), $number, $decimals );
86 }
87
88 /**
89 * Convert time supplied from database query into specified date format.
90 *
91 * @since bbPress (r2455)
92 *
93 * @param int|object $post Optional. Default is global post object. A post_id or
94 * post object
95 * @param string $d Optional. Default is 'U'. Either 'G', 'U', or php date
96 * format
97 * @param bool $translate Optional. Default is false. Whether to translate the
98 * result
99 * @uses mysql2date() To convert the format
100 * @uses apply_filters() Calls 'bbp_convert_date' with the time, date format
101 * and translate bool
102 * @return string Returns timestamp
103 */
104 function bbp_convert_date( $time, $d = 'U', $translate = false ) {
105 $time = mysql2date( $d, $time, $translate );
106
107 return apply_filters( 'bbp_convert_date', $time, $d, $translate );
108 }
109
110 /**
111 * Output formatted time to display human readable time difference.
112 *
113 * @since bbPress (r2544)
114 *
115 * @param $time Unix timestamp from which the difference begins.
116 * @uses bbp_get_time_since() To get the formatted time
117 */
118 function bbp_time_since( $time ) {
119 echo bbp_get_time_since( $time );
120 }
121 /**
122 * Return formatted time to display human readable time difference.
123 *
124 * @since bbPress (r2544)
125 *
126 * @param $time Unix timestamp from which the difference begins.
127 * @uses current_time() To get the current time in mysql format
128 * @uses human_time_diff() To get the time differene in since format
129 * @uses apply_filters() Calls 'bbp_get_time_since' with the time
130 * difference and time
131 * @return string Formatted time
132 */
133 function bbp_get_time_since( $time ) {
134 return apply_filters( 'bbp_get_time_since', human_time_diff( $time, current_time( 'timestamp' ) ), $time );
135 }
136
137 /**
138 * Formats the reason for editing the topic/reply.
139 *
140 * Does these things:
141 * - Trimming
142 * - Removing periods from the end of the string
143 * - Trimming again
144 *
145 * @since bbPress (r2782)
146 *
147 * @param int $topic_id Optional. Topic id
148 * @return string Status of topic
149 */
150 function bbp_format_revision_reason( $reason = '' ) {
151 $reason = (string) $reason;
152
153 // Format reason for proper display
154 if ( empty( $reason ) )
155 return $reason;
156
157 // Trimming
158 $reason = trim( $reason );
159
160 // We add our own full stop.
161 while ( substr( $reason, -1 ) == '.' )
162 $reason = substr( $reason, 0, -1 );
163
164 // Trim again
165 $reason = trim( $reason );
166
167 return $reason;
168 }
169
170 /** Misc **********************************************************************/
171
172 /**
173 * The plugin version of bbPress comes with two topic display options:
174 * - Traditional: Topics are included in the reply loop (default)
175 * - New Style: Topics appear as "lead" posts, ahead of replies
176 *
177 * @since bbPress (r2954)
178 *
179 * @param $show_lead Optional. Default false
180 * @return bool Yes if the topic appears as a lead, otherwise false
181 */
182 function bbp_show_lead_topic( $show_lead = false ) {
183 return apply_filters( 'bbp_show_lead_topic', (bool) $show_lead );
184 }
185
186 /**
187 * Append 'view=all' to query string if it's already there from referer
188 *
189 * @since bbPress (r3325)
190 *
191 * @param string $original_link Original Link to be modified
192 * @param bool $force Override bbp_get_view_all() check
193 * @uses current_user_can() To check if the current user can moderate
194 * @uses add_query_arg() To add args to the url
195 * @uses apply_filters() Calls 'bbp_add_view_all' with the link and original link
196 * @return string The link with 'view=all' appended if necessary
197 */
198 function bbp_add_view_all( $original_link = '', $force = false ) {
199
200 // Are we appending the view=all vars?
201 if ( bbp_get_view_all() || !empty( $force ) )
202 $link = add_query_arg( array( 'view' => 'all' ), $original_link );
203 else
204 $link = $original_link;
205
206 return apply_filters( 'bbp_add_view_all', $link, $original_link );
207 }
208
209 /**
210 * Remove 'view=all' from query string
211 *
212 * @since bbPress (r3325)
213 *
214 * @param string $original_link Original Link to be modified
215 * @uses current_user_can() To check if the current user can moderate
216 * @uses add_query_arg() To add args to the url
217 * @uses apply_filters() Calls 'bbp_add_view_all' with the link and original link
218 * @return string The link with 'view=all' appended if necessary
219 */
220 function bbp_remove_view_all( $original_link = '' ) {
221
222 // Are we appending the view=all vars?
223 $link = remove_query_arg( 'view', $original_link );
224
225 return apply_filters( 'bbp_add_view_all', $link, $original_link );
226 }
227
228 /**
229 * If current user can and is vewing all topics/replies
230 *
231 * @since bbPress (r3325)
232 *
233 * @uses current_user_can() To check if the current user can moderate
234 * @uses apply_filters() Calls 'bbp_get_view_all' with the link and original link
235 * @return bool Whether current user can and is viewing all
236 */
237 function bbp_get_view_all( $cap = 'moderate' ) {
238
239 $retval = ( ( !empty( $_GET['view'] ) && ( 'all' == $_GET['view'] ) && current_user_can( $cap ) ) );
240
241 return apply_filters( 'bbp_get_view_all', (bool) $retval );
242 }
243
244 /**
245 * Assist pagination by returning correct page number
246 *
247 * @since bbPress (r2628)
248 *
249 * @uses get_query_var() To get the 'paged' value
250 * @return int Current page number
251 */
252 function bbp_get_paged() {
253 global $wp_query;
254
255 // Make sure to not paginate widget queries
256 if ( !bbp_is_query_name( 'bbp_widget' ) ) {
257
258 // Check the query var
259 if ( get_query_var( 'paged' ) ) {
260 $paged = get_query_var( 'paged' );
261
262 // Check query paged
263 } elseif ( !empty( $wp_query->query['paged'] ) ) {
264 $paged = $wp_query->query['paged'];
265 }
266
267 // Paged found
268 if ( !empty( $paged ) ) {
269 return (int) $paged;
270 }
271 }
272
273 // Default to first page
274 return 1;
275 }
276
277 /**
278 * Fix post author id on post save
279 *
280 * When a logged in user changes the status of an anonymous reply or topic, or
281 * edits it, the post_author field is set to the logged in user's id. This
282 * function fixes that.
283 *
284 * @since bbPress (r2734)
285 *
286 * @param array $data Post data
287 * @param array $postarr Original post array (includes post id)
288 * @uses bbp_get_topic_post_type() To get the topic post type
289 * @uses bbp_get_reply_post_type() To get the reply post type
290 * @uses bbp_is_topic_anonymous() To check if the topic is by an anonymous user
291 * @uses bbp_is_reply_anonymous() To check if the reply is by an anonymous user
292 * @return array Data
293 */
294 function bbp_fix_post_author( $data = array(), $postarr = array() ) {
295 global $bbp;
296
297 // Post is not being updated or the post_author is already 0, return
298 if ( empty( $postarr['ID'] ) || empty( $data['post_author'] ) )
299 return $data;
300
301 // Post is not a topic or reply, return
302 if ( !in_array( $data['post_type'], array( bbp_get_topic_post_type(), bbp_get_reply_post_type() ) ) )
303 return $data;
304
305 // Is the post by an anonymous user?
306 if ( ( bbp_get_topic_post_type() == $data['post_type'] && !bbp_is_topic_anonymous( $postarr['ID'] ) ) ||
307 ( bbp_get_reply_post_type() == $data['post_type'] && !bbp_is_reply_anonymous( $postarr['ID'] ) ) )
308 return $data;
309
310 // The post is being updated. It is a topic or a reply and is written by an anonymous user.
311 // Set the post_author back to 0
312 $data['post_author'] = 0;
313
314 return $data;
315 }
316
317 /**
318 * Check the date against the _bbp_edit_lock setting.
319 *
320 * @since bbPress (r3133)
321 *
322 * @param string $post_date_gmt
323 *
324 * @uses get_option() Get the edit lock time
325 * @uses current_time() Get the current time
326 * @uses strtotime() Convert strings to time
327 * @uses apply_filters() Allow output to be manipulated
328 *
329 * @return bool
330 */
331 function bbp_past_edit_lock( $post_date_gmt ) {
332
333 // Assume editing is allowed
334 $retval = false;
335
336 // Bail if empty date
337 if ( ! empty( $post_date_gmt ) ) {
338
339 // Period of time
340 $lockable = '+' . get_option( '_bbp_edit_lock', '5' ) . ' minutes';
341
342 // Now
343 $cur_time = current_time( 'timestamp', true );
344
345 // Add lockable time to post time
346 $lock_time = strtotime( $lockable, strtotime( $post_date_gmt ) );
347
348 // Compare
349 if ( $cur_time >= $lock_time ) {
350 $retval = true;
351 }
352 }
353
354 return apply_filters( 'bbp_past_edit_lock', (bool) $retval, $cur_time, $lock_time, $post_date_gmt );
355 }
356
357 /** Statistics ****************************************************************/
358
359 /**
360 * Get the forum statistics
361 *
362 * @since bbPress (r2769)
363 *
364 * @param mixed $args Optional. The function supports these arguments (all
365 * default to true):
366 * - count_users: Count users?
367 * - count_forums: Count forums?
368 * - count_topics: Count topics? If set to false, private, spammed and trashed
369 * topics are also not counted.
370 * - count_private_topics: Count private topics? (only counted if the current
371 * user has read_private_topics cap)
372 * - count_spammed_topics: Count spammed topics? (only counted if the current
373 * user has edit_others_topics cap)
374 * - count_trashed_topics: Count trashed topics? (only counted if the current
375 * user has view_trash cap)
376 * - count_replies: Count replies? If set to false, private, spammed and
377 * trashed replies are also not counted.
378 * - count_private_replies: Count private replies? (only counted if the current
379 * user has read_private_replies cap)
380 * - count_spammed_replies: Count spammed replies? (only counted if the current
381 * user has edit_others_replies cap)
382 * - count_trashed_replies: Count trashed replies? (only counted if the current
383 * user has view_trash cap)
384 * - count_tags: Count tags? If set to false, empty tags are also not counted
385 * - count_empty_tags: Count empty tags?
386 * @uses bbp_count_users() To count the number of registered users
387 * @uses bbp_get_forum_post_type() To get the forum post type
388 * @uses bbp_get_topic_post_type() To get the topic post type
389 * @uses bbp_get_reply_post_type() To get the reply post type
390 * @uses wp_count_posts() To count the number of forums, topics and replies
391 * @uses wp_count_terms() To count the number of topic tags
392 * @uses current_user_can() To check if the user is capable of doing things
393 * @uses number_format_i18n() To format the number
394 * @uses apply_filters() Calls 'bbp_get_statistics' with the statistics and args
395 * @return object Walked forum tree
396 */
397 function bbp_get_statistics( $args = '' ) {
398 global $bbp;
399
400 $defaults = array (
401 'count_users' => true,
402 'count_forums' => true,
403 'count_topics' => true,
404 'count_private_topics' => true,
405 'count_spammed_topics' => true,
406 'count_trashed_topics' => true,
407 'count_replies' => true,
408 'count_private_replies' => true,
409 'count_spammed_replies' => true,
410 'count_trashed_replies' => true,
411 'count_tags' => true,
412 'count_empty_tags' => true
413 );
414
415 $r = wp_parse_args( $args, $defaults );
416 extract( $r );
417
418 // Users
419 if ( !empty( $count_users ) )
420 $user_count = bbp_get_total_users();
421
422 // Forums
423 if ( !empty( $count_forums ) ) {
424 $forum_count = wp_count_posts( bbp_get_forum_post_type() );
425 $forum_count = $forum_count->publish;
426 }
427
428 // Topics
429 if ( !empty( $count_topics ) ) {
430
431 $all_topics = wp_count_posts( bbp_get_topic_post_type() );
432
433 // Published (publish + closed)
434 $topic_count = $all_topics->publish + $all_topics->{$bbp->closed_status_id};
435
436 if ( current_user_can( 'read_private_topics' ) || current_user_can( 'edit_others_topics' ) || current_user_can( 'view_trash' ) ) {
437
438 // Private
439 $topics['private'] = ( !empty( $count_private_topics ) && current_user_can( 'read_private_topics' ) ) ? (int) $all_topics->private : 0;
440
441 // Spam
442 $topics['spammed'] = ( !empty( $count_spammed_topics ) && current_user_can( 'edit_others_topics' ) ) ? (int) $all_topics->{$bbp->spam_status_id} : 0;
443
444 // Trash
445 $topics['trashed'] = ( !empty( $count_trashed_topics ) && current_user_can( 'view_trash' ) ) ? (int) $all_topics->{$bbp->trash_status_id} : 0;
446
447 // Total hidden (private + spam + trash)
448 $topic_count_hidden = $topics['private'] + $topics['spammed'] + $topics['trashed'];
449
450 // Generate the hidden topic count's title attribute
451 $topic_titles[] = !empty( $topics['private'] ) ? sprintf( __( 'Private: %s', 'bbpress' ), number_format_i18n( $topics['private'] ) ) : '';
452 $topic_titles[] = !empty( $topics['spammed'] ) ? sprintf( __( 'Spammed: %s', 'bbpress' ), number_format_i18n( $topics['spammed'] ) ) : '';
453 $topic_titles[] = !empty( $topics['trashed'] ) ? sprintf( __( 'Trashed: %s', 'bbpress' ), number_format_i18n( $topics['trashed'] ) ) : '';
454
455 // Compile the hidden topic title
456 $hidden_topic_title = implode( ' | ', array_filter( $topic_titles ) );
457 }
458 }
459
460 // Replies
461 if ( !empty( $count_replies ) ) {
462
463 $all_replies = wp_count_posts( bbp_get_reply_post_type() );
464
465 // Published
466 $reply_count = $all_replies->publish;
467
468 if ( current_user_can( 'read_private_replies' ) || current_user_can( 'edit_others_replies' ) || current_user_can( 'view_trash' ) ) {
469
470 // Private
471 $replies['private'] = ( !empty( $count_private_replies ) && current_user_can( 'read_private_replies' ) ) ? (int) $all_replies->private : 0;
472
473 // Spam
474 $replies['spammed'] = ( !empty( $count_spammed_replies ) && current_user_can( 'edit_others_replies' ) ) ? (int) $all_replies->{$bbp->spam_status_id} : 0;
475
476 // Trash
477 $replies['trashed'] = ( !empty( $count_trashed_replies ) && current_user_can( 'view_trash' ) ) ? (int) $all_replies->{$bbp->trash_status_id} : 0;
478
479 // Total hidden (private + spam + trash)
480 $reply_count_hidden = $replies['private'] + $replies['spammed'] + $replies['trashed'];
481
482 // Generate the hidden topic count's title attribute
483 $reply_titles[] = !empty( $replies['private'] ) ? sprintf( __( 'Private: %s', 'bbpress' ), number_format_i18n( $replies['private'] ) ) : '';
484 $reply_titles[] = !empty( $replies['spammed'] ) ? sprintf( __( 'Spammed: %s', 'bbpress' ), number_format_i18n( $replies['spammed'] ) ) : '';
485 $reply_titles[] = !empty( $replies['trashed'] ) ? sprintf( __( 'Trashed: %s', 'bbpress' ), number_format_i18n( $replies['trashed'] ) ) : '';
486
487 // Compile the hidden replies title
488 $hidden_reply_title = implode( ' | ', array_filter( $reply_titles ) );
489
490 }
491 }
492
493 // Topic Tags
494 if ( !empty( $count_tags ) ) {
495
496 // Get the count
497 $topic_tag_count = wp_count_terms( bbp_get_topic_tag_tax_id(), array( 'hide_empty' => true ) );
498
499 // Empty tags
500 if ( !empty( $count_empty_tags ) && current_user_can( 'edit_topic_tags' ) ) {
501 $empty_topic_tag_count = wp_count_terms( bbp_get_topic_tag_tax_id() ) - $topic_tag_count;
502 }
503 }
504
505 // Tally the tallies
506 $statistics = compact( 'user_count', 'forum_count', 'topic_count', 'topic_count_hidden', 'reply_count', 'reply_count_hidden', 'topic_tag_count', 'empty_topic_tag_count' );
507 $statistics = array_map( 'absint', $statistics );
508 $statistics = array_map( 'number_format_i18n', $statistics );
509
510 // Add the hidden (topic/reply) count title attribute strings because we don't need to run the math functions on these (see above)
511 if ( isset( $hidden_topic_title ) )
512 $statistics['hidden_topic_title'] = $hidden_topic_title;
513
514 if ( isset( $hidden_reply_title ) )
515 $statistics['hidden_reply_title'] = $hidden_reply_title;
516
517 return apply_filters( 'bbp_get_statistics', $statistics, $args );
518 }
519
520 /** Views *********************************************************************/
521
522 /**
523 * Get the registered views
524 *
525 * Does nothing much other than return the {@link $bbp->views} variable
526 *
527 * @since bbPress (r2789)
528 *
529 * @return array Views
530 */
531 function bbp_get_views() {
532 global $bbp;
533
534 return $bbp->views;
535 }
536
537 /**
538 * Register a bbPress view
539 *
540 * @todo Implement feeds - See {@link http://trac.bbpress.org/ticket/1422}
541 *
542 * @since bbPress (r2789)
543 *
544 * @param string $view View name
545 * @param string $title View title
546 * @param mixed $query_args {@link bbp_has_topics()} arguments.
547 * @param bool $feed Have a feed for the view? Defaults to true. NOT IMPLEMENTED
548 * @uses sanitize_title() To sanitize the view name
549 * @uses esc_html() To sanitize the view title
550 * @return array The just registered (but processed) view
551 */
552 function bbp_register_view( $view, $title, $query_args = '', $feed = true ) {
553 global $bbp;
554
555 $view = sanitize_title( $view );
556 $title = esc_html( $title );
557
558 if ( empty( $view ) || empty( $title ) )
559 return false;
560
561 $query_args = wp_parse_args( $query_args );
562
563 // Set exclude_stickies to true if it wasn't supplied
564 if ( !isset( $query_args['show_stickies'] ) )
565 $query_args['show_stickies'] = false;
566
567 $bbp->views[$view]['title'] = $title;
568 $bbp->views[$view]['query'] = $query_args;
569 $bbp->views[$view]['feed'] = $feed;
570
571 return $bbp->views[$view];
572 }
573
574 /**
575 * Deregister a bbPress view
576 *
577 * @since bbPress (r2789)
578 *
579 * @param string $view View name
580 * @uses sanitize_title() To sanitize the view name
581 * @return bool False if the view doesn't exist, true on success
582 */
583 function bbp_deregister_view( $view ) {
584 global $bbp;
585
586 $view = sanitize_title( $view );
587
588 if ( !isset( $bbp->views[$view] ) )
589 return false;
590
591 unset( $bbp->views[$view] );
592
593 return true;
594 }
595
596 /**
597 * Run the view's query
598 *
599 * @since bbPress (r2789)
600 *
601 * @param string $view Optional. View id
602 * @param mixed $new_args New arguments. See {@link bbp_has_topics()}
603 * @uses bbp_get_view_id() To get the view id
604 * @uses bbp_get_view_query_args() To get the view query args
605 * @uses sanitize_title() To sanitize the view name
606 * @uses bbp_has_topics() To make the topics query
607 * @return bool False if the view doesn't exist, otherwise if topics are there
608 */
609 function bbp_view_query( $view = '', $new_args = '' ) {
610 global $bbp;
611
612 if ( !$view = bbp_get_view_id( $view ) )
613 return false;
614
615 $query_args = bbp_get_view_query_args( $view );
616
617 if ( !empty( $new_args ) ) {
618 $new_args = wp_parse_args( $new_args );
619 $query_args = array_merge( $query_args, $new_args );
620 }
621
622 return bbp_has_topics( $query_args );
623 }
624
625 /**
626 * Run the view's query's arguments
627 *
628 * @since bbPress (r2789)
629 *
630 * @param string $view View name
631 * @uses bbp_get_view_id() To get the view id
632 * @uses sanitize_title() To sanitize the view name
633 * @return array Query arguments
634 */
635 function bbp_get_view_query_args( $view ) {
636 global $bbp;
637
638 if ( !$views = bbp_get_view_id( $view ) )
639 return false;
640
641 return $bbp->views[$view]['query'];
642 }
643
644 /** New/edit topic/reply helpers **********************************************/
645
646 /**
647 * Filter anonymous post data
648 *
649 * We use REMOTE_ADDR here directly. If you are behind a proxy, you should
650 * ensure that it is properly set, such as in wp-config.php, for your
651 * environment. See {@link http://core.trac.wordpress.org/ticket/9235}
652 *
653 * If there are any errors, those are directly added to {@link bbPress:errors}
654 *
655 * @since bbPress (r2734)
656 *
657 * @param mixed $args Optional. If no args are there, then $_POST values are
658 * used.
659 * @param bool $is_edit Optional. Is the topic/reply being edited? There are no
660 * IP checks then.
661 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_name' with the
662 * anonymous user name
663 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_email' with the
664 * anonymous user email
665 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_ip' with the
666 * anonymous user's ip address
667 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_website' with the
668 * anonymous user website
669 * @return bool|array False on errors, values in an array on success
670 */
671 function bbp_filter_anonymous_post_data( $args = '', $is_edit = false ) {
672 global $bbp;
673
674 // Assign variables
675 $defaults = array (
676 'bbp_anonymous_name' => !empty( $_POST['bbp_anonymous_name'] ) ? $_POST['bbp_anonymous_name'] : false,
677 'bbp_anonymous_email' => !empty( $_POST['bbp_anonymous_email'] ) ? $_POST['bbp_anonymous_email'] : false,
678 'bbp_anonymous_website' => !empty( $_POST['bbp_anonymous_website'] ) ? $_POST['bbp_anonymous_website'] : false,
679 );
680
681 $r = wp_parse_args( $args, $defaults );
682 extract( $r );
683
684 // Filter variables and add errors if necessary
685 if ( !$bbp_anonymous_name = apply_filters( 'bbp_pre_anonymous_post_author_name', $bbp_anonymous_name ) )
686 bbp_add_error( 'bbp_anonymous_name', __( '<strong>ERROR</strong>: Invalid author name submitted!', 'bbpress' ) );
687
688 if ( !$bbp_anonymous_email = apply_filters( 'bbp_pre_anonymous_post_author_email', $bbp_anonymous_email ) )
689 bbp_add_error( 'bbp_anonymous_email', __( '<strong>ERROR</strong>: Invalid email address submitted!', 'bbpress' ) );
690
691 // Website is optional
692 $bbp_anonymous_website = apply_filters( 'bbp_pre_anonymous_post_author_website', $bbp_anonymous_website );
693
694 if ( !bbp_has_errors() )
695 $retval = compact( 'bbp_anonymous_name', 'bbp_anonymous_email', 'bbp_anonymous_website' );
696 else
697 $retval = false;
698
699 // Finally, return sanitized data or false
700 return apply_filters( 'bbp_filter_anonymous_post_data', $retval, $args );
701 }
702
703 /**
704 * Check for duplicate topics/replies
705 *
706 * Check to make sure that a user is not making a duplicate post
707 *
708 * @since bbPress (r2763)
709 *
710 * @param array $post_data Contains information about the comment
711 * @uses current_user_can() To check if the current user can throttle
712 * @uses get_meta_sql() To generate the meta sql for checking anonymous email
713 * @uses apply_filters() Calls 'bbp_check_for_duplicate_query' with the
714 * duplicate check query and post data
715 * @uses wpdb::get_var() To execute our query and get the var back
716 * @uses get_post_meta() To get the anonymous user email post meta
717 * @uses do_action() Calls 'bbp_post_duplicate_trigger' with the post data when
718 * it is found that it is a duplicate
719 * @return bool True if it is not a duplicate, false if it is
720 */
721 function bbp_check_for_duplicate( $post_data ) {
722
723 // No duplicate checks for those who can throttle
724 if ( current_user_can( 'throttle' ) )
725 return true;
726
727 global $bbp, $wpdb;
728
729 extract( $post_data, EXTR_SKIP );
730
731 // Check for anonymous post
732 if ( empty( $post_author ) && !empty( $anonymous_data['bbp_anonymous_email'] ) ) {
733
734 // WP 3.2
735 if ( function_exists( 'get_meta_sql' ) )
736 $clauses = get_meta_sql( array( array( 'key' => '_bbp_anonymous_email', 'value' => $anonymous_data['bbp_anonymous_email'] ) ), 'post', $wpdb->posts, 'ID' );
737
738 // WP 3.1
739 elseif ( function_exists( '_get_meta_sql' ) )
740 $clauses = _get_meta_sql( array( array( 'key' => '_bbp_anonymous_email', 'value' => $anonymous_data['bbp_anonymous_email'] ) ), 'post', $wpdb->posts, 'ID' );
741
742 $join = $clauses['join'];
743 $where = $clauses['where'];
744 } else{
745 $join = $where = '';
746 }
747
748 // Simple duplicate check
749 // Expected slashed ($post_type, $post_parent, $post_author, $post_content, $anonymous_data)
750 $dupe = "SELECT ID FROM {$wpdb->posts} {$join} WHERE post_type = '{$post_type}' AND post_status != '{$bbp->trash_status_id}' AND post_author = {$post_author} AND post_content = '{$post_content}' {$where}";
751 $dupe .= !empty( $post_parent ) ? " AND post_parent = '{$post_parent}'" : '';
752 $dupe .= " LIMIT 1";
753 $dupe = apply_filters( 'bbp_check_for_duplicate_query', $dupe, $post_data );
754
755 if ( $wpdb->get_var( $dupe ) ) {
756 do_action( 'bbp_check_for_duplicate_trigger', $post_data );
757 return false;
758 }
759
760 return true;
761 }
762
763 /**
764 * Check for flooding
765 *
766 * Check to make sure that a user is not making too many posts in a short amount
767 * of time.
768 *
769 * @since bbPress (r2734)
770 *
771 * @param false|array $anonymous_data Optional - if it's an anonymous post. Do
772 * not supply if supplying $author_id.
773 * Should have key 'bbp_author_ip'.
774 * Should be sanitized (see
775 * {@link bbp_filter_anonymous_post_data()}
776 * for sanitization)
777 * @param int $author_id Optional. Supply if it's a post by a logged in user.
778 * Do not supply if supplying $anonymous_data.
779 * @uses get_option() To get the throttle time
780 * @uses get_transient() To get the last posted transient of the ip
781 * @uses get_user_meta() To get the last posted meta of the user
782 * @uses current_user_can() To check if the current user can throttle
783 * @return bool True if there is no flooding, true if there is
784 */
785 function bbp_check_for_flood( $anonymous_data = false, $author_id = 0 ) {
786
787 // Option disabled. No flood checks.
788 if ( !$throttle_time = get_option( '_bbp_throttle_time' ) )
789 return true;
790
791 if ( !empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
792 $last_posted = get_transient( '_bbp_' . bbp_current_author_ip() . '_last_posted' );
793 if ( !empty( $last_posted ) && time() < $last_posted + $throttle_time )
794 return false;
795 } elseif ( !empty( $author_id ) ) {
796 $author_id = (int) $author_id;
797 $last_posted = get_user_meta( $author_id, '_bbp_last_posted', true );
798
799 if ( isset( $last_posted ) && time() < $last_posted + $throttle_time && !current_user_can( 'throttle' ) )
800 return false;
801 } else {
802 return false;
803 }
804
805 return true;
806 }
807
808 /** Subscriptions *************************************************************/
809
810 /**
811 * Sends notification emails for new posts
812 *
813 * Gets new post's ID and check if there are subscribed users to that topic, and
814 * if there are, send notifications
815 *
816 * @since bbPress (r2668)
817 *
818 * @param int $reply_id ID of the newly made reply
819 * @uses bbp_is_subscriptions_active() To check if the subscriptions are active
820 * @uses bbp_get_reply() To get the reply
821 * @uses bbp_get_topic() To get the reply's topic
822 * @uses get_the_author_meta() To get the author's display name
823 * @uses do_action() Calls 'bbp_pre_notify_subscribers' with the reply id and
824 * topic id
825 * @uses bbp_get_topic_subscribers() To get the topic subscribers
826 * @uses apply_filters() Calls 'bbp_subscription_mail_message' with the
827 * message, reply id, topic id and user id
828 * @uses get_userdata() To get the user data
829 * @uses wp_mail() To send the mail
830 * @uses do_action() Calls 'bbp_post_notify_subscribers' with the reply id
831 * and topic id
832 * @return bool True on success, false on failure
833 */
834 function bbp_notify_subscribers( $reply_id = 0 ) {
835 global $bbp, $wpdb;
836
837 if ( !bbp_is_subscriptions_active() )
838 return false;
839
840 if ( empty( $reply_id ) )
841 return false;
842
843 if ( !$reply = bbp_get_reply( $reply_id ) )
844 return false;
845
846 if ( empty( $reply->post_parent ) )
847 return false;
848
849 if ( !$topic = bbp_get_topic( $reply->post_parent ) )
850 return false;
851
852 if ( !$poster_name = get_the_author_meta( 'display_name', $reply->post_author ) )
853 return false;
854
855 do_action( 'bbp_pre_notify_subscribers', $reply->ID, $topic->ID );
856
857 // Get the users who have favorited the topic and have subscriptions on
858 if ( !$user_ids = bbp_get_topic_subscribers( $topic->ID, true ) )
859 return false;
860
861 // Loop through users
862 foreach ( (array) $user_ids as $user_id ) {
863
864 // Don't send notifications to the person who made the post
865 if ( $user_id == $reply->post_author )
866 continue;
867
868 // For plugins
869 if ( !$message = apply_filters( 'bbp_subscription_mail_message', __( "%1\$s wrote:\n\n%2\$s\n\nPost Link: %3\$s\n\nYou're getting this mail because you subscribed to the topic, visit the topic and login to unsubscribe.", 'bbpress' ), $reply->ID, $topic->ID, $user_id ) )
870 continue;
871
872 // Get user data of this user
873 $user = get_userdata( $user_id );
874
875 // Send notification email
876 wp_mail(
877 $user->user_email,
878 apply_filters( 'bbp_subscription_mail_title', '[' . get_option( 'blogname' ) . '] ' . $topic->post_title, $reply->ID, $topic->ID ),
879 sprintf( $message, $poster_name, strip_tags( $reply->post_content ), bbp_get_reply_url( $reply->ID ) )
880 );
881 }
882
883 do_action( 'bbp_post_notify_subscribers', $reply->ID, $topic->ID );
884
885 return true;
886 }
887
888 /** Login *********************************************************************/
889
890 /**
891 * Return a clean and reliable logout URL
892 *
893 * @param string $url URL
894 * @param string $redirect_to Where to redirect to?
895 * @uses add_query_arg() To add args to the url
896 * @uses apply_filters() Calls 'bbp_logout_url' with the url and redirect to
897 * @return string The url
898 */
899 function bbp_logout_url( $url = '', $redirect_to = '' ) {
900
901 // Make sure we are directing somewhere
902 if ( empty( $redirect_to ) && !strstr( $url, 'redirect_to' ) ) {
903
904 // Rejig the $redirect_to
905 if ( !isset( $_SERVER['REDIRECT_URL'] ) || ( $redirect_to != home_url( $_SERVER['REDIRECT_URL'] ) ) ) {
906 $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '';
907 }
908
909 $redirect_to = home_url( isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '' );
910
911 // Sanitize $redirect_to and add it to full $url
912 $redirect_to = add_query_arg( array( 'loggedout' => 'true' ), esc_url( $redirect_to ) );
913 $url = add_query_arg( array( 'redirect_to' => urlencode( $redirect_to ) ), $url );
914 }
915
916 // Filter and return
917 return apply_filters( 'bbp_logout_url', $url, $redirect_to );
918 }
919
920 /** Queries *******************************************************************/
921
922 /**
923 * Adjusts topic and reply queries to exclude items that might be contained
924 * inside hidden or private forums that the user does not have the capability
925 * to view.
926 *
927 * @since bbPress (r3291)
928 *
929 * @param WP_Query $posts_query
930 *
931 * @uses apply_filters()
932 * @uses bbp_exclude_forum_ids()
933 * @uses bbp_get_topic_post_type()
934 * @uses bbp_get_reply_post_type()
935
936 * @return WP_Query
937 */
938 function bbp_pre_get_posts_exclude_forums( $posts_query ) {
939
940 // Bail if all forums are explicitly allowed
941 if ( true === apply_filters( 'bbp_include_all_forums', $posts_query ) )
942 return $posts_query;
943
944 // Bail if $posts_query is not an object or of incorrect class
945 if ( !is_object( $posts_query ) || ( 'WP_Query' != get_class( $posts_query ) ) )
946 return $posts_query;
947
948 // Bail if filters are suppressed on this query
949 if ( true == $posts_query->get( 'suppress_filters' ) )
950 return $posts_query;
951
952 // There are forums that need to be excluded
953 if ( $forum_ids = bbp_exclude_forum_ids( 'meta_query' ) ) {
954
955 // Only exclude forums on bbPress queries
956 switch ( $posts_query->get( 'post_type' ) ) {
957
958 // Topics
959 case bbp_get_topic_post_type() :
960
961 // Replies
962 case bbp_get_reply_post_type() :
963
964 // Topics and replies
965 case array( bbp_get_topic_post_type(), bbp_get_reply_post_type() ) :
966
967 // Get any existing meta queries
968 $meta_query = $posts_query->get( 'meta_query' );
969
970 // Add our meta query to existing
971 $meta_query[] = $forum_ids;
972
973 // Set the meta_query var
974 $posts_query->set( 'meta_query', $meta_query );
975
976 break;
977 }
978 }
979
980 // Return possibly adjusted query
981 return $posts_query;
982 }
983
984 /**
985 * Adds ability to include or exclude specific post_parent ID's
986 *
987 * @since bbPress (r2996)
988 *
989 * @global DB $wpdb
990 * @global WP $wp
991 * @param string $where
992 * @param WP_Query $object
993 * @return string
994 */
995 function bbp_query_post_parent__in( $where, $object = '' ) {
996 global $wpdb, $wp;
997
998 // Noop if WP core supports this already
999 if ( in_array( 'post_parent__in', $wp->private_query_vars ) )
1000 return $where;
1001
1002 // Bail if no object passed
1003 if ( empty( $object ) )
1004 return $where;
1005
1006 // Only 1 post_parent so return $where
1007 if ( is_numeric( $object->query_vars['post_parent'] ) )
1008 return $where;
1009
1010 // Including specific post_parent's
1011 if ( ! empty( $object->query_vars['post_parent__in'] ) ) {
1012 $ids = implode( ',', array_map( 'absint', $object->query_vars['post_parent__in'][0] ) );
1013 $where .= " AND $wpdb->posts.post_parent IN ($ids)";
1014
1015 // Excluding specific post_parent's
1016 } elseif ( ! empty( $object->query_vars['post_parent__not_in'] ) ) {
1017 $ids = implode( ',', array_map( 'absint', $object->query_vars['post_parent__not_in'][0] ) );
1018 $where .= " AND $wpdb->posts.post_parent NOT IN ($ids)";
1019 }
1020
1021 // Return possibly modified $where
1022 return $where;
1023 }
1024 //add_filter( 'posts_where', 'bbp_query_post_parent__in', 10, 2 );
1025
1026 /**
1027 * Query the DB and get the last public post_id that has parent_id as post_parent
1028 *
1029 * @param int $parent_id Parent id
1030 * @param string $post_type Post type. Defaults to 'post'
1031 * @uses bbp_get_topic_post_type() To get the topic post type
1032 * @uses wp_cache_get() To check if there is a cache of the last child id
1033 * @uses wpdb::prepare() To prepare the query
1034 * @uses wpdb::get_var() To get the result of the query in a variable
1035 * @uses wp_cache_set() To set the cache for future use
1036 * @uses apply_filters() Calls 'bbp_get_public_child_last_id' with the child
1037 * id, parent id and post type
1038 * @return int The last active post_id
1039 */
1040 function bbp_get_public_child_last_id( $parent_id = 0, $post_type = 'post' ) {
1041 global $wpdb;
1042
1043 // Bail if nothing passed
1044 if ( empty( $parent_id ) )
1045 return false;
1046
1047 // The ID of the cached query
1048 $cache_id = 'bbp_parent_' . $parent_id . '_type_' . $post_type . '_child_last_id';
1049 $post_status = array( 'publish' );
1050
1051 // Add closed status if topic post type
1052 if ( $post_type == bbp_get_topic_post_type() )
1053 $post_status[] = $bbp->closed_status_id;
1054
1055 // Join post statuses together
1056 $post_status = "'" . join( "', '", $post_status ) . "'";
1057
1058 // Check for cache and set if needed
1059 if ( !$child_id = wp_cache_get( $cache_id, 'bbpress' ) ) {
1060 $child_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = '%s' ORDER BY ID DESC LIMIT 1;", $parent_id, $post_type ) );
1061 wp_cache_set( $cache_id, $child_id, 'bbpress' );
1062 }
1063
1064 // Filter and return
1065 return apply_filters( 'bbp_get_public_child_last_id', (int) $child_id, (int) $parent_id, $post_type );
1066 }
1067
1068 /**
1069 * Query the DB and get a count of public children
1070 *
1071 * @param int $parent_id Parent id
1072 * @param string $post_type Post type. Defaults to 'post'
1073 * @uses bbp_get_topic_post_type() To get the topic post type
1074 * @uses wp_cache_get() To check if there is a cache of the children count
1075 * @uses wpdb::prepare() To prepare the query
1076 * @uses wpdb::get_var() To get the result of the query in a variable
1077 * @uses wp_cache_set() To set the cache for future use
1078 * @uses apply_filters() Calls 'bbp_get_public_child_count' with the child
1079 * count, parent id and post type
1080 * @return int The number of children
1081 */
1082 function bbp_get_public_child_count( $parent_id = 0, $post_type = 'post' ) {
1083 global $wpdb, $bbp;
1084
1085 // Bail if nothing passed
1086 if ( empty( $parent_id ) )
1087 return false;
1088
1089 // The ID of the cached query
1090 $cache_id = 'bbp_parent_' . $parent_id . '_type_' . $post_type . '_child_count';
1091 $post_status = array( 'publish' );
1092
1093 // Add closed status if topic post type
1094 if ( $post_type == bbp_get_topic_post_type() )
1095 $post_status[] = $bbp->closed_status_id;
1096
1097 // Join post statuses together
1098 $post_status = "'" . join( "', '", $post_status ) . "'";
1099
1100 // Check for cache and set if needed
1101 if ( !$child_count = wp_cache_get( $cache_id, 'bbpress' ) ) {
1102 $child_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = '%s';", $parent_id, $post_type ) );
1103 wp_cache_set( $cache_id, $child_count, 'bbpress' );
1104 }
1105
1106 // Filter and return
1107 return apply_filters( 'bbp_get_public_child_count', (int) $child_count, (int) $parent_id, $post_type );
1108 }
1109
1110 /**
1111 * Query the DB and get a the child id's of public children
1112 *
1113 * @param int $parent_id Parent id
1114 * @param string $post_type Post type. Defaults to 'post'
1115 * @uses bbp_get_topic_post_type() To get the topic post type
1116 * @uses wp_cache_get() To check if there is a cache of the children
1117 * @uses wpdb::prepare() To prepare the query
1118 * @uses wpdb::get_col() To get the result of the query in an array
1119 * @uses wp_cache_set() To set the cache for future use
1120 * @uses apply_filters() Calls 'bbp_get_public_child_ids' with the child ids,
1121 * parent id and post type
1122 * @return array The array of children
1123 */
1124 function bbp_get_public_child_ids( $parent_id = 0, $post_type = 'post' ) {
1125 global $wpdb, $bbp;
1126
1127 // Bail if nothing passed
1128 if ( empty( $parent_id ) )
1129 return false;
1130
1131 // The ID of the cached query
1132 $cache_id = 'bbp_parent_public_' . $parent_id . '_type_' . $post_type . '_child_ids';
1133 $post_status = array( 'publish' );
1134
1135 // Add closed status if topic post type
1136 if ( $post_type == bbp_get_topic_post_type() )
1137 $post_status[] = $bbp->closed_status_id;
1138
1139 // Join post statuses together
1140 $post_status = "'" . join( "', '", $post_status ) . "'";
1141
1142 // Check for cache and set if needed
1143 if ( !$child_ids = wp_cache_get( $cache_id, 'bbpress' ) ) {
1144 $child_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = '%s' ORDER BY ID DESC;", $parent_id, $post_type ) );
1145 wp_cache_set( $cache_id, $child_ids, 'bbpress' );
1146 }
1147
1148 // Filter and return
1149 return apply_filters( 'bbp_get_public_child_ids', $child_ids, (int) $parent_id, $post_type );
1150 }
1151 /**
1152 * Query the DB and get a the child id's of all children
1153 *
1154 * @param int $parent_id Parent id
1155 * @param string $post_type Post type. Defaults to 'post'
1156 * @uses bbp_get_topic_post_type() To get the topic post type
1157 * @uses wp_cache_get() To check if there is a cache of the children
1158 * @uses wpdb::prepare() To prepare the query
1159 * @uses wpdb::get_col() To get the result of the query in an array
1160 * @uses wp_cache_set() To set the cache for future use
1161 * @uses apply_filters() Calls 'bbp_get_public_child_ids' with the child ids,
1162 * parent id and post type
1163 * @return array The array of children
1164 */
1165 function bbp_get_all_child_ids( $parent_id = 0, $post_type = 'post' ) {
1166 global $wpdb, $bbp;
1167
1168 // Bail if nothing passed
1169 if ( empty( $parent_id ) )
1170 return false;
1171
1172 // The ID of the cached query
1173 $cache_id = 'bbp_parent_all_' . $parent_id . '_type_' . $post_type . '_child_ids';
1174 $post_status = array( 'publish' );
1175
1176 // Extra post statuses based on post type
1177 switch ( $post_type ) {
1178
1179 // Forum
1180 case bbp_get_forum_post_type() :
1181 $post_status[] = 'private';
1182 $post_status[] = $bbp->hidden_status_id;
1183 break;
1184
1185 // Topic
1186 case bbp_get_topic_post_type() :
1187 $post_status[] = $bbp->closed_status_id;
1188 $post_status[] = $bbp->trash_status_id;
1189 $post_status[] = $bbp->spam_status_id;
1190 break;
1191
1192 // Reply
1193 case bbp_get_reply_post_type() :
1194 $post_status[] = $bbp->trash_status_id;
1195 $post_status[] = $bbp->spam_status_id;
1196 break;
1197 }
1198
1199 // Join post statuses together
1200 $post_status = "'" . join( "', '", $post_status ) . "'";
1201
1202 // Check for cache and set if needed
1203 if ( !$child_ids = wp_cache_get( $cache_id, 'bbpress' ) ) {
1204 $child_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = '%s' ORDER BY ID DESC;", $parent_id, $post_type ) );
1205 wp_cache_set( $cache_id, $child_ids, 'bbpress' );
1206 }
1207
1208 // Filter and return
1209 return apply_filters( 'bbp_get_all_child_ids', $child_ids, (int) $parent_id, $post_type );
1210 }
1211
1212 /** Feeds *********************************************************************/
1213
1214 /**
1215 * This function is hooked into the WordPress 'request' action and is
1216 * responsible for sniffing out the query vars and serving up RSS2 feeds if
1217 * the stars align and the user has requested a feed of any bbPress type.
1218 *
1219 * @since bbPress (r3171)
1220 *
1221 * @global WP_Query $wp_query
1222 * @global bbPress $bbp
1223 * @param array $query_vars
1224 * @return array
1225 */
1226 function bbp_request_feed_trap( $query_vars ) {
1227 global $wp_query, $bbp;
1228
1229 // Looking at a feed
1230 if ( isset( $query_vars['feed'] ) ) {
1231
1232 // Forum Feed
1233 if ( isset( $query_vars['post_type'] ) ) {
1234
1235 // What bbPress post type are we looking for feeds on?
1236 switch ( $query_vars['post_type'] ) {
1237
1238 // Forum
1239 case bbp_get_forum_post_type() :
1240
1241 // Single forum
1242 if ( isset( $query_vars[bbp_get_forum_post_type()] ) ) {
1243
1244 // Load up our own query
1245 $wp_query = new WP_Query( array(
1246 'post_type' => bbp_get_forum_post_type(),
1247 'name' => $query_vars[bbp_get_forum_post_type()]
1248 ) );
1249
1250 // Forum replies
1251 if ( !empty( $_GET['type'] ) && ( bbp_get_reply_post_type() == $_GET['type'] ) ) {
1252
1253 // The query
1254 $the_query = array(
1255 'author' => 0,
1256 'post_type' => bbp_get_reply_post_type(),
1257 'post_parent' => 'any',
1258 'post_status' => join( ',', array( 'publish', $bbp->closed_status_id ) ),
1259 'posts_per_page' => get_option( '_bbp_replies_per_rss_page', 25 ),
1260 'order' => 'DESC',
1261 'meta_query' => array( array(
1262 'key' => '_bbp_forum_id',
1263 'value' => bbp_get_forum_id(),
1264 'compare' => '='
1265 ) )
1266 );
1267
1268 // Output the feed
1269 bbp_display_replies_feed_rss2( $the_query );
1270
1271 // Forum topics
1272 } else {
1273
1274 // The query
1275 $the_query = array(
1276 'author' => 0,
1277 'post_type' => bbp_get_topic_post_type(),
1278 'post_parent' => bbp_get_forum_id(),
1279 'post_status' => join( ',', array( 'publish', $bbp->closed_status_id ) ),
1280 'posts_per_page' => get_option( '_bbp_topics_per_rss_page', 25 ),
1281 'order' => 'DESC',
1282 'meta_query' => array( array(
1283 'key' => '_bbp_forum_id',
1284 'value' => bbp_get_forum_id(),
1285 'compare' => '='
1286 ) )
1287 );
1288
1289 // Output the feed
1290 bbp_display_topics_feed_rss2( $the_query );
1291 }
1292 }
1293
1294 break;
1295
1296 // Topic - Show replies
1297 case bbp_get_topic_post_type() :
1298
1299 // Single topic
1300 if ( isset( $query_vars[bbp_get_topic_post_type()] ) ) {
1301
1302 // Load up our own query
1303 $wp_query = new WP_Query( array(
1304 'post_type' => bbp_get_topic_post_type(),
1305 'name' => $query_vars[bbp_get_topic_post_type()]
1306 ) );
1307
1308 // Output the feed
1309 bbp_display_replies_feed_rss2();
1310
1311 // All topics
1312 } else {
1313
1314 // The query
1315 $the_query = array(
1316 'author' => 0,
1317 'post_parent' => 'any',
1318 'posts_per_page' => get_option( '_bbp_topics_per_rss_page', 25 ),
1319 'show_stickies' => false,
1320 );
1321
1322 // Output the feed
1323 bbp_display_topics_feed_rss2( $the_query );
1324 }
1325
1326 break;
1327
1328 // Replies
1329 case bbp_get_reply_post_type() :
1330
1331 // The query
1332 $the_query = array(
1333 'posts_per_page' => get_option( '_bbp_replies_per_rss_page', 25 ),
1334 'meta_query' => array( array( ) )
1335 );
1336
1337 // All replies
1338 if ( !isset( $query_vars[bbp_get_reply_post_type()] ) ) {
1339 bbp_display_replies_feed_rss2( $the_query );
1340 }
1341
1342 break;
1343 }
1344 }
1345 }
1346
1347 // No feed so continue on
1348 return $query_vars;
1349 }
1350
1351 /** Errors ********************************************************************/
1352
1353 /**
1354 * Adds an error message to later be output in the theme
1355 *
1356 * @since bbPress (r3381)
1357 *
1358 * @global bbPress $bbp
1359 *
1360 * @see WP_Error()
1361 * @uses WP_Error::add();
1362 *
1363 * @param string $code Unique code for the error message
1364 * @param string $message Translated error message
1365 * @param string $data Any additional data passed with the error message
1366 */
1367 function bbp_add_error( $code = '', $message = '', $data = '' ) {
1368 global $bbp;
1369
1370 $bbp->errors->add( $code, $message, $data );
1371 }
1372
1373 /**
1374 * Check if error messages exist in queue
1375 *
1376 * @since bbPress (r3381)
1377 *
1378 * @global bbPress $bbp
1379 *
1380 * @see WP_Error()
1381 *
1382 * @uses is_wp_error()
1383 * @usese WP_Error::get_error_codes()
1384 */
1385 function bbp_has_errors() {
1386 global $bbp;
1387
1388 // Assume no errors
1389 $has_errors = false;
1390
1391 // Check for errors
1392 if ( $bbp->errors->get_error_codes() )
1393 $has_errors = true;
1394
1395 // Filter return value
1396 $has_errors = apply_filters( 'bbp_has_errors', $has_errors, $bbp->errors );
1397
1398 return $has_errors;
1399 }
1400
1401 ?>
1402