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

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