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

1,632 lines 50.7 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
443 $defaults = array (
444 'count_users' => true,
445 'count_forums' => true,
446 'count_topics' => true,
447 'count_private_topics' => true,
448 'count_spammed_topics' => true,
449 'count_trashed_topics' => true,
450 'count_replies' => true,
451 'count_private_replies' => true,
452 'count_spammed_replies' => true,
453 'count_trashed_replies' => true,
454 'count_tags' => true,
455 'count_empty_tags' => true
456 );
457
458 $r = wp_parse_args( $args, $defaults );
459 extract( $r );
460
461 // Users
462 if ( !empty( $count_users ) )
463 $user_count = bbp_get_total_users();
464
465 // Forums
466 if ( !empty( $count_forums ) ) {
467 $forum_count = wp_count_posts( bbp_get_forum_post_type() );
468 $forum_count = $forum_count->publish;
469 }
470
471 // Post statuses
472 $private = bbp_get_private_status_id();
473 $spam = bbp_get_spam_status_id();
474 $trash = bbp_get_trash_status_id();
475 $closed = bbp_get_closed_status_id();
476
477 // Topics
478 if ( !empty( $count_topics ) ) {
479
480 $all_topics = wp_count_posts( bbp_get_topic_post_type() );
481
482 // Published (publish + closed)
483 $topic_count = $all_topics->publish + $all_topics->{$closed};
484
485 if ( current_user_can( 'read_private_topics' ) || current_user_can( 'edit_others_topics' ) || current_user_can( 'view_trash' ) ) {
486
487 // Private
488 $topics['private'] = ( !empty( $count_private_topics ) && current_user_can( 'read_private_topics' ) ) ? (int) $all_topics->{$private} : 0;
489
490 // Spam
491 $topics['spammed'] = ( !empty( $count_spammed_topics ) && current_user_can( 'edit_others_topics' ) ) ? (int) $all_topics->{$spam} : 0;
492
493 // Trash
494 $topics['trashed'] = ( !empty( $count_trashed_topics ) && current_user_can( 'view_trash' ) ) ? (int) $all_topics->{$trash} : 0;
495
496 // Total hidden (private + spam + trash)
497 $topic_count_hidden = $topics['private'] + $topics['spammed'] + $topics['trashed'];
498
499 // Generate the hidden topic count's title attribute
500 $topic_titles[] = !empty( $topics['private'] ) ? sprintf( __( 'Private: %s', 'bbpress' ), number_format_i18n( $topics['private'] ) ) : '';
501 $topic_titles[] = !empty( $topics['spammed'] ) ? sprintf( __( 'Spammed: %s', 'bbpress' ), number_format_i18n( $topics['spammed'] ) ) : '';
502 $topic_titles[] = !empty( $topics['trashed'] ) ? sprintf( __( 'Trashed: %s', 'bbpress' ), number_format_i18n( $topics['trashed'] ) ) : '';
503
504 // Compile the hidden topic title
505 $hidden_topic_title = implode( ' | ', array_filter( $topic_titles ) );
506 }
507 }
508
509 // Replies
510 if ( !empty( $count_replies ) ) {
511
512 $all_replies = wp_count_posts( bbp_get_reply_post_type() );
513
514 // Published
515 $reply_count = $all_replies->publish;
516
517 if ( current_user_can( 'read_private_replies' ) || current_user_can( 'edit_others_replies' ) || current_user_can( 'view_trash' ) ) {
518
519 // Private
520 $replies['private'] = ( !empty( $count_private_replies ) && current_user_can( 'read_private_replies' ) ) ? (int) $all_replies->{$private} : 0;
521
522 // Spam
523 $replies['spammed'] = ( !empty( $count_spammed_replies ) && current_user_can( 'edit_others_replies' ) ) ? (int) $all_replies->{$spam} : 0;
524
525 // Trash
526 $replies['trashed'] = ( !empty( $count_trashed_replies ) && current_user_can( 'view_trash' ) ) ? (int) $all_replies->{$trash} : 0;
527
528 // Total hidden (private + spam + trash)
529 $reply_count_hidden = $replies['private'] + $replies['spammed'] + $replies['trashed'];
530
531 // Generate the hidden topic count's title attribute
532 $reply_titles[] = !empty( $replies['private'] ) ? sprintf( __( 'Private: %s', 'bbpress' ), number_format_i18n( $replies['private'] ) ) : '';
533 $reply_titles[] = !empty( $replies['spammed'] ) ? sprintf( __( 'Spammed: %s', 'bbpress' ), number_format_i18n( $replies['spammed'] ) ) : '';
534 $reply_titles[] = !empty( $replies['trashed'] ) ? sprintf( __( 'Trashed: %s', 'bbpress' ), number_format_i18n( $replies['trashed'] ) ) : '';
535
536 // Compile the hidden replies title
537 $hidden_reply_title = implode( ' | ', array_filter( $reply_titles ) );
538
539 }
540 }
541
542 // Topic Tags
543 if ( !empty( $count_tags ) ) {
544
545 // Get the count
546 $topic_tag_count = wp_count_terms( bbp_get_topic_tag_tax_id(), array( 'hide_empty' => true ) );
547
548 // Empty tags
549 if ( !empty( $count_empty_tags ) && current_user_can( 'edit_topic_tags' ) ) {
550 $empty_topic_tag_count = wp_count_terms( bbp_get_topic_tag_tax_id() ) - $topic_tag_count;
551 }
552 }
553
554 // Tally the tallies
555 $statistics = compact( 'user_count', 'forum_count', 'topic_count', 'topic_count_hidden', 'reply_count', 'reply_count_hidden', 'topic_tag_count', 'empty_topic_tag_count' );
556 $statistics = array_map( 'absint', $statistics );
557 $statistics = array_map( 'number_format_i18n', $statistics );
558
559 // Add the hidden (topic/reply) count title attribute strings because we don't need to run the math functions on these (see above)
560 if ( isset( $hidden_topic_title ) )
561 $statistics['hidden_topic_title'] = $hidden_topic_title;
562
563 if ( isset( $hidden_reply_title ) )
564 $statistics['hidden_reply_title'] = $hidden_reply_title;
565
566 return apply_filters( 'bbp_get_statistics', $statistics, $args );
567 }
568
569 /** Views *********************************************************************/
570
571 /**
572 * Get the registered views
573 *
574 * Does nothing much other than return the {@link $bbp->views} variable
575 *
576 * @since bbPress (r2789)
577 *
578 * @return array Views
579 */
580 function bbp_get_views() {
581 global $bbp;
582
583 return $bbp->views;
584 }
585
586 /**
587 * Register a bbPress view
588 *
589 * @todo Implement feeds - See {@link http://trac.bbpress.org/ticket/1422}
590 *
591 * @since bbPress (r2789)
592 *
593 * @param string $view View name
594 * @param string $title View title
595 * @param mixed $query_args {@link bbp_has_topics()} arguments.
596 * @param bool $feed Have a feed for the view? Defaults to true. NOT IMPLEMENTED
597 * @uses sanitize_title() To sanitize the view name
598 * @uses esc_html() To sanitize the view title
599 * @return array The just registered (but processed) view
600 */
601 function bbp_register_view( $view, $title, $query_args = '', $feed = true ) {
602 global $bbp;
603
604 $view = sanitize_title( $view );
605 $title = esc_html( $title );
606
607 if ( empty( $view ) || empty( $title ) )
608 return false;
609
610 $query_args = wp_parse_args( $query_args );
611
612 // Set exclude_stickies to true if it wasn't supplied
613 if ( !isset( $query_args['show_stickies'] ) )
614 $query_args['show_stickies'] = false;
615
616 $bbp->views[$view]['title'] = $title;
617 $bbp->views[$view]['query'] = $query_args;
618 $bbp->views[$view]['feed'] = $feed;
619
620 return $bbp->views[$view];
621 }
622
623 /**
624 * Deregister a bbPress view
625 *
626 * @since bbPress (r2789)
627 *
628 * @param string $view View name
629 * @uses sanitize_title() To sanitize the view name
630 * @return bool False if the view doesn't exist, true on success
631 */
632 function bbp_deregister_view( $view ) {
633 global $bbp;
634
635 $view = sanitize_title( $view );
636
637 if ( !isset( $bbp->views[$view] ) )
638 return false;
639
640 unset( $bbp->views[$view] );
641
642 return true;
643 }
644
645 /**
646 * Run the view's query
647 *
648 * @since bbPress (r2789)
649 *
650 * @param string $view Optional. View id
651 * @param mixed $new_args New arguments. See {@link bbp_has_topics()}
652 * @uses bbp_get_view_id() To get the view id
653 * @uses bbp_get_view_query_args() To get the view query args
654 * @uses sanitize_title() To sanitize the view name
655 * @uses bbp_has_topics() To make the topics query
656 * @return bool False if the view doesn't exist, otherwise if topics are there
657 */
658 function bbp_view_query( $view = '', $new_args = '' ) {
659 global $bbp;
660
661 if ( !$view = bbp_get_view_id( $view ) )
662 return false;
663
664 $query_args = bbp_get_view_query_args( $view );
665
666 if ( !empty( $new_args ) ) {
667 $new_args = wp_parse_args( $new_args );
668 $query_args = array_merge( $query_args, $new_args );
669 }
670
671 return bbp_has_topics( $query_args );
672 }
673
674 /**
675 * Run the view's query's arguments
676 *
677 * @since bbPress (r2789)
678 *
679 * @param string $view View name
680 * @uses bbp_get_view_id() To get the view id
681 * @uses sanitize_title() To sanitize the view name
682 * @return array Query arguments
683 */
684 function bbp_get_view_query_args( $view ) {
685 global $bbp;
686
687 if ( !$views = bbp_get_view_id( $view ) )
688 return false;
689
690 return $bbp->views[$view]['query'];
691 }
692
693 /** New/edit topic/reply helpers **********************************************/
694
695 /**
696 * Filter anonymous post data
697 *
698 * We use REMOTE_ADDR here directly. If you are behind a proxy, you should
699 * ensure that it is properly set, such as in wp-config.php, for your
700 * environment. See {@link http://core.trac.wordpress.org/ticket/9235}
701 *
702 * If there are any errors, those are directly added to {@link bbPress:errors}
703 *
704 * @since bbPress (r2734)
705 *
706 * @param mixed $args Optional. If no args are there, then $_POST values are
707 * used.
708 * @param bool $is_edit Optional. Is the topic/reply being edited? There are no
709 * IP checks then.
710 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_name' with the
711 * anonymous user name
712 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_email' with the
713 * anonymous user email
714 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_ip' with the
715 * anonymous user's ip address
716 * @uses apply_filters() Calls 'bbp_pre_anonymous_post_author_website' with the
717 * anonymous user website
718 * @return bool|array False on errors, values in an array on success
719 */
720 function bbp_filter_anonymous_post_data( $args = '', $is_edit = false ) {
721
722 // Assign variables
723 $defaults = array (
724 'bbp_anonymous_name' => !empty( $_POST['bbp_anonymous_name'] ) ? $_POST['bbp_anonymous_name'] : false,
725 'bbp_anonymous_email' => !empty( $_POST['bbp_anonymous_email'] ) ? $_POST['bbp_anonymous_email'] : false,
726 'bbp_anonymous_website' => !empty( $_POST['bbp_anonymous_website'] ) ? $_POST['bbp_anonymous_website'] : false,
727 );
728
729 $r = wp_parse_args( $args, $defaults );
730 extract( $r );
731
732 // Filter variables and add errors if necessary
733 if ( !$bbp_anonymous_name = apply_filters( 'bbp_pre_anonymous_post_author_name', $bbp_anonymous_name ) )
734 bbp_add_error( 'bbp_anonymous_name', __( '<strong>ERROR</strong>: Invalid author name submitted!', 'bbpress' ) );
735
736 if ( !$bbp_anonymous_email = apply_filters( 'bbp_pre_anonymous_post_author_email', $bbp_anonymous_email ) )
737 bbp_add_error( 'bbp_anonymous_email', __( '<strong>ERROR</strong>: Invalid email address submitted!', 'bbpress' ) );
738
739 // Website is optional
740 $bbp_anonymous_website = apply_filters( 'bbp_pre_anonymous_post_author_website', $bbp_anonymous_website );
741
742 if ( !bbp_has_errors() )
743 $retval = compact( 'bbp_anonymous_name', 'bbp_anonymous_email', 'bbp_anonymous_website' );
744 else
745 $retval = false;
746
747 // Finally, return sanitized data or false
748 return apply_filters( 'bbp_filter_anonymous_post_data', $retval, $args );
749 }
750
751 /**
752 * Check for duplicate topics/replies
753 *
754 * Check to make sure that a user is not making a duplicate post
755 *
756 * @since bbPress (r2763)
757 *
758 * @param array $post_data Contains information about the comment
759 * @uses current_user_can() To check if the current user can throttle
760 * @uses get_meta_sql() To generate the meta sql for checking anonymous email
761 * @uses apply_filters() Calls 'bbp_check_for_duplicate_query' with the
762 * duplicate check query and post data
763 * @uses wpdb::get_var() To execute our query and get the var back
764 * @uses get_post_meta() To get the anonymous user email post meta
765 * @uses do_action() Calls 'bbp_post_duplicate_trigger' with the post data when
766 * it is found that it is a duplicate
767 * @return bool True if it is not a duplicate, false if it is
768 */
769 function bbp_check_for_duplicate( $post_data ) {
770
771 // No duplicate checks for those who can throttle
772 if ( current_user_can( 'throttle' ) )
773 return true;
774
775 global $wpdb;
776
777 extract( $post_data, EXTR_SKIP );
778
779 // Check for anonymous post
780 if ( empty( $post_author ) && !empty( $anonymous_data['bbp_anonymous_email'] ) ) {
781
782 // WP 3.2
783 if ( 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 // WP 3.1
787 elseif ( function_exists( '_get_meta_sql' ) )
788 $clauses = _get_meta_sql( array( array( 'key' => '_bbp_anonymous_email', 'value' => $anonymous_data['bbp_anonymous_email'] ) ), 'post', $wpdb->posts, 'ID' );
789
790 $join = $clauses['join'];
791 $where = $clauses['where'];
792 } else{
793 $join = $where = '';
794 }
795
796 // Simple duplicate check
797 // Expected slashed ($post_type, $post_parent, $post_author, $post_content, $anonymous_data)
798 $status = bbp_get_trash_status_id();
799 $dupe = "SELECT ID FROM {$wpdb->posts} {$join} WHERE post_type = '{$post_type}' AND post_status != '{$status}' AND post_author = {$post_author} AND post_content = '{$post_content}' {$where}";
800 $dupe .= !empty( $post_parent ) ? " AND post_parent = '{$post_parent}'" : '';
801 $dupe .= " LIMIT 1";
802 $dupe = apply_filters( 'bbp_check_for_duplicate_query', $dupe, $post_data );
803
804 if ( $wpdb->get_var( $dupe ) ) {
805 do_action( 'bbp_check_for_duplicate_trigger', $post_data );
806 return false;
807 }
808
809 return true;
810 }
811
812 /**
813 * Check for flooding
814 *
815 * Check to make sure that a user is not making too many posts in a short amount
816 * of time.
817 *
818 * @since bbPress (r2734)
819 *
820 * @param false|array $anonymous_data Optional - if it's an anonymous post. Do
821 * not supply if supplying $author_id.
822 * Should have key 'bbp_author_ip'.
823 * Should be sanitized (see
824 * {@link bbp_filter_anonymous_post_data()}
825 * for sanitization)
826 * @param int $author_id Optional. Supply if it's a post by a logged in user.
827 * Do not supply if supplying $anonymous_data.
828 * @uses get_option() To get the throttle time
829 * @uses get_transient() To get the last posted transient of the ip
830 * @uses get_user_meta() To get the last posted meta of the user
831 * @uses current_user_can() To check if the current user can throttle
832 * @return bool True if there is no flooding, true if there is
833 */
834 function bbp_check_for_flood( $anonymous_data = false, $author_id = 0 ) {
835
836 // Option disabled. No flood checks.
837 if ( !$throttle_time = get_option( '_bbp_throttle_time' ) )
838 return true;
839
840 if ( !empty( $anonymous_data ) && is_array( $anonymous_data ) ) {
841 $last_posted = get_transient( '_bbp_' . bbp_current_author_ip() . '_last_posted' );
842 if ( !empty( $last_posted ) && time() < $last_posted + $throttle_time )
843 return false;
844 } elseif ( !empty( $author_id ) ) {
845 $author_id = (int) $author_id;
846 $last_posted = get_user_meta( $author_id, '_bbp_last_posted', true );
847
848 if ( isset( $last_posted ) && time() < $last_posted + $throttle_time && !current_user_can( 'throttle' ) )
849 return false;
850 } else {
851 return false;
852 }
853
854 return true;
855 }
856
857 /**
858 * Checks topics and replies against the discussion blacklist of blocked keys
859 *
860 * @since bbPress (r3446)
861 *
862 * @param array $anonymous_data Anonymous user data
863 * @param int $author_id Topic or reply author ID
864 * @param string $title The title of the content
865 * @param string $content The content being posted
866 * @uses is_super_admin() Allow super admins to bypass blacklist
867 * @uses bbp_current_author_ip() To get current user IP address
868 * @uses bbp_current_author_ua() To get current user agent
869 * @return bool True if test is passed, false if fail
870 */
871 function bbp_check_for_blacklist( $anonymous_data = false, $author_id = 0, $title = '', $content = '' ) {
872
873 // Bail if super admin is author
874 if ( is_super_admin( $author_id ) )
875 return true;
876
877 // Define local variable
878 $post = array();
879
880 /** Blacklist *************************************************************/
881
882 // Get the moderation keys
883 $blacklist = trim( get_option( 'blacklist_keys' ) );
884
885 // Bail if blacklist is empty
886 if ( empty( $blacklist ) )
887 return true;
888
889 /** User Data *************************************************************/
890
891 // Map anonymous user data
892 if ( !empty( $anonymous_data ) ) {
893 $post['author'] = $anonymous_data['bbp_anonymous_name'];
894 $post['email'] = $anonymous_data['bbp_anonymous_email'];
895 $post['url'] = $anonymous_data['bbp_anonymous_website'];
896
897 // Map current user data
898 } elseif ( !empty( $author_id ) ) {
899
900 // Get author data
901 $user = get_userdata( $author_id );
902
903 // If data exists, map it
904 if ( !empty( $user ) ) {
905 $post['author'] = $user->display_name;
906 $post['email'] = $user->user_email;
907 $post['url'] = $user->user_url;
908 }
909 }
910
911 // Current user IP and user agent
912 $post['user_ip'] = bbp_current_author_ip();
913 $post['user_ua'] = bbp_current_author_ua();
914
915 // Post title and content
916 $post['title'] = $title;
917 $post['content'] = $content;
918
919 /** Words *****************************************************************/
920
921 // Get words separated by new lines
922 $words = explode( "\n", $blacklist );
923
924 // Loop through words
925 foreach ( (array) $words as $word ) {
926
927 // Trim the whitespace from the word
928 $word = trim( $word );
929
930 // Skip empty lines
931 if ( empty( $word ) ) { continue; }
932
933 // Do some escaping magic so that '#' chars in the
934 // spam words don't break things:
935 $word = preg_quote( $word, '#' );
936 $pattern = "#$word#i";
937
938 // Loop through post data
939 foreach( $post as $post_data ) {
940
941 // Check each user data for current word
942 if ( preg_match( $pattern, $post_data ) ) {
943
944 // Post does not pass
945 return false;
946 }
947 }
948 }
949
950 // Check passed successfully
951 return true;
952 }
953
954 /** Subscriptions *************************************************************/
955
956 /**
957 * Sends notification emails for new posts
958 *
959 * Gets new post's ID and check if there are subscribed users to that topic, and
960 * if there are, send notifications
961 *
962 * @since bbPress (r2668)
963 *
964 * @param int $reply_id ID of the newly made reply
965 * @uses bbp_is_subscriptions_active() To check if the subscriptions are active
966 * @uses bbp_get_reply_id() To validate the reply ID
967 * @uses bbp_get_reply() To get the reply
968 * @uses bbp_get_reply_topic_id() To get the topic ID of the reply
969 * @uses bbp_is_reply_published() To make sure the reply is published
970 * @uses bbp_get_topic_id() To validate the topic ID
971 * @uses bbp_get_topic() To get the reply's topic
972 * @uses bbp_is_topic_published() To make sure the topic is published
973 * @uses get_the_author_meta() To get the author's display name
974 * @uses do_action() Calls 'bbp_pre_notify_subscribers' with the reply id and
975 * topic id
976 * @uses bbp_get_topic_subscribers() To get the topic subscribers
977 * @uses apply_filters() Calls 'bbp_subscription_mail_message' with the
978 * message, reply id, topic id and user id
979 * @uses get_userdata() To get the user data
980 * @uses wp_mail() To send the mail
981 * @uses do_action() Calls 'bbp_post_notify_subscribers' with the reply id
982 * and topic id
983 * @return bool True on success, false on failure
984 */
985 function bbp_notify_subscribers( $reply_id = 0 ) {
986 global $wpdb;
987
988 // Bail if subscriptions are turned off
989 if ( !bbp_is_subscriptions_active() )
990 return false;
991
992 /** Reply *****************************************************************/
993
994 // Validate reply ID and bail if empty
995 $reply_id = bbp_get_reply_id( $reply_id );
996 if ( empty( $reply_id ) )
997 return false;
998
999 // Get the reply and bail if empty
1000 $reply = bbp_get_reply( $reply_id );
1001 if ( empty( $reply ) )
1002 return false;
1003
1004 // Bail if reply is not published
1005 if ( !bbp_is_reply_published( $reply_id ) )
1006 return false;
1007
1008 /** Topic *****************************************************************/
1009
1010 // Get topic ID and bail if empty
1011 $topic_id = bbp_get_reply_topic_id( $reply_id );
1012 if ( empty( $topic_id ) )
1013 return false;
1014
1015 // Get the topic and bail if empty
1016 $topic = bbp_get_topic( $topic_id );
1017 if ( empty( $topic ) )
1018 return false;
1019
1020 // Bail if reply is not published
1021 if ( !bbp_is_topic_published( $reply_id ) )
1022 return false;
1023
1024 /** User ******************************************************************/
1025
1026 // Get subscribers and bail if empty
1027 $user_ids = bbp_get_topic_subscribers( $topic_id, true );
1028 if ( empty( $user_ids ) )
1029 return false;
1030
1031 /** Mail ******************************************************************/
1032
1033 do_action( 'bbp_pre_notify_subscribers', $reply_id, $topic_id, $user_ids );
1034
1035 // Loop through users
1036 foreach ( (array) $user_ids as $user_id ) {
1037
1038 // Don't send notifications to the person who made the post
1039 if ( (int) $user_id == (int) $reply->post_author )
1040 continue;
1041
1042 // For plugins to filter messages per reply/topic/user
1043 $message = __( "%1\$s wrote:\n\n%2\$s\n\nPost Link: %3\$s\n\nYou are recieving this email because you subscribed to it. Login and visit the topic to unsubscribe from these emails.", 'bbpress' );
1044 $message = apply_filters( 'bbp_subscription_mail_message', sprintf( $message, $poster_name, strip_tags( $reply->post_content ), bbp_get_reply_url( $reply_id ) ), $reply_id, $topic_id, $user_id );
1045 if ( empty( $message ) )
1046 continue;
1047
1048 // For plugins to filter titles per reply/topic/user
1049 $subject = apply_filters( 'bbp_subscription_mail_title', '[' . get_option( 'blogname' ) . '] ' . $topic->post_title, $reply_id, $topic_id, $user_id );
1050 if ( empty( $subject ) )
1051 continue;
1052
1053 // Get user data of this user
1054 $user = get_userdata( $user_id );
1055
1056 // Send notification email
1057 wp_mail( $user->user_email, $subject, $message );
1058 }
1059
1060 do_action( 'bbp_post_notify_subscribers', $reply_id, $topic_id, $user_ids );
1061
1062 return true;
1063 }
1064
1065 /** Login *********************************************************************/
1066
1067 /**
1068 * Return a clean and reliable logout URL
1069 *
1070 * @param string $url URL
1071 * @param string $redirect_to Where to redirect to?
1072 * @uses add_query_arg() To add args to the url
1073 * @uses apply_filters() Calls 'bbp_logout_url' with the url and redirect to
1074 * @return string The url
1075 */
1076 function bbp_logout_url( $url = '', $redirect_to = '' ) {
1077
1078 // Make sure we are directing somewhere
1079 if ( empty( $redirect_to ) && !strstr( $url, 'redirect_to' ) ) {
1080
1081 // Rejig the $redirect_to
1082 if ( !isset( $_SERVER['REDIRECT_URL'] ) || ( $redirect_to != home_url( $_SERVER['REDIRECT_URL'] ) ) ) {
1083 $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '';
1084 }
1085
1086 $redirect_to = home_url( isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '' );
1087
1088 // Sanitize $redirect_to and add it to full $url
1089 $redirect_to = add_query_arg( array( 'loggedout' => 'true' ), esc_url( $redirect_to ) );
1090 $url = add_query_arg( array( 'redirect_to' => urlencode( $redirect_to ) ), $url );
1091 }
1092
1093 // Filter and return
1094 return apply_filters( 'bbp_logout_url', $url, $redirect_to );
1095 }
1096
1097 /** Queries *******************************************************************/
1098
1099 /**
1100 * Adds ability to include or exclude specific post_parent ID's
1101 *
1102 * @since bbPress (r2996)
1103 *
1104 * @global DB $wpdb
1105 * @global WP $wp
1106 * @param string $where
1107 * @param WP_Query $object
1108 * @return string
1109 */
1110 function bbp_query_post_parent__in( $where, $object = '' ) {
1111 global $wpdb, $wp;
1112
1113 // Noop if WP core supports this already
1114 if ( in_array( 'post_parent__in', $wp->private_query_vars ) )
1115 return $where;
1116
1117 // Bail if no object passed
1118 if ( empty( $object ) )
1119 return $where;
1120
1121 // Only 1 post_parent so return $where
1122 if ( is_numeric( $object->query_vars['post_parent'] ) )
1123 return $where;
1124
1125 // Including specific post_parent's
1126 if ( ! empty( $object->query_vars['post_parent__in'] ) ) {
1127 $ids = implode( ',', array_map( 'absint', $object->query_vars['post_parent__in'][0] ) );
1128 $where .= " AND $wpdb->posts.post_parent IN ($ids)";
1129
1130 // Excluding specific post_parent's
1131 } elseif ( ! empty( $object->query_vars['post_parent__not_in'] ) ) {
1132 $ids = implode( ',', array_map( 'absint', $object->query_vars['post_parent__not_in'][0] ) );
1133 $where .= " AND $wpdb->posts.post_parent NOT IN ($ids)";
1134 }
1135
1136 // Return possibly modified $where
1137 return $where;
1138 }
1139 //add_filter( 'posts_where', 'bbp_query_post_parent__in', 10, 2 );
1140
1141 /**
1142 * Query the DB and get the last public post_id that has parent_id as post_parent
1143 *
1144 * @param int $parent_id Parent id
1145 * @param string $post_type Post type. Defaults to 'post'
1146 * @uses bbp_get_topic_post_type() To get the topic post type
1147 * @uses wp_cache_get() To check if there is a cache of the last child id
1148 * @uses wpdb::prepare() To prepare the query
1149 * @uses wpdb::get_var() To get the result of the query in a variable
1150 * @uses wp_cache_set() To set the cache for future use
1151 * @uses apply_filters() Calls 'bbp_get_public_child_last_id' with the child
1152 * id, parent id and post type
1153 * @return int The last active post_id
1154 */
1155 function bbp_get_public_child_last_id( $parent_id = 0, $post_type = 'post' ) {
1156 global $wpdb;
1157
1158 // Bail if nothing passed
1159 if ( empty( $parent_id ) )
1160 return false;
1161
1162 // The ID of the cached query
1163 $cache_id = 'bbp_parent_' . $parent_id . '_type_' . $post_type . '_child_last_id';
1164 $post_status = array( bbp_get_public_status_id() );
1165
1166 // Add closed status if topic post type
1167 if ( $post_type == bbp_get_topic_post_type() )
1168 $post_status[] = bbp_get_closed_status_id();
1169
1170 // Join post statuses together
1171 $post_status = "'" . join( "', '", $post_status ) . "'";
1172
1173 // Check for cache and set if needed
1174 if ( !$child_id = wp_cache_get( $cache_id, 'bbpress' ) ) {
1175 $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 ) );
1176 wp_cache_set( $cache_id, $child_id, 'bbpress' );
1177 }
1178
1179 // Filter and return
1180 return apply_filters( 'bbp_get_public_child_last_id', (int) $child_id, (int) $parent_id, $post_type );
1181 }
1182
1183 /**
1184 * Query the DB and get a count of public children
1185 *
1186 * @param int $parent_id Parent id
1187 * @param string $post_type Post type. Defaults to 'post'
1188 * @uses bbp_get_topic_post_type() To get the topic post type
1189 * @uses wp_cache_get() To check if there is a cache of the children count
1190 * @uses wpdb::prepare() To prepare the query
1191 * @uses wpdb::get_var() To get the result of the query in a variable
1192 * @uses wp_cache_set() To set the cache for future use
1193 * @uses apply_filters() Calls 'bbp_get_public_child_count' with the child
1194 * count, parent id and post type
1195 * @return int The number of children
1196 */
1197 function bbp_get_public_child_count( $parent_id = 0, $post_type = 'post' ) {
1198 global $wpdb;
1199
1200 // Bail if nothing passed
1201 if ( empty( $parent_id ) )
1202 return false;
1203
1204 // The ID of the cached query
1205 $cache_id = 'bbp_parent_' . $parent_id . '_type_' . $post_type . '_child_count';
1206 $post_status = array( bbp_get_public_status_id() );
1207
1208 // Add closed status if topic post type
1209 if ( $post_type == bbp_get_topic_post_type() )
1210 $post_status[] = bbp_get_closed_status_id();
1211
1212 // Join post statuses together
1213 $post_status = "'" . join( "', '", $post_status ) . "'";
1214
1215 // Check for cache and set if needed
1216 if ( !$child_count = wp_cache_get( $cache_id, 'bbpress' ) ) {
1217 $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 ) );
1218 wp_cache_set( $cache_id, $child_count, 'bbpress' );
1219 }
1220
1221 // Filter and return
1222 return apply_filters( 'bbp_get_public_child_count', (int) $child_count, (int) $parent_id, $post_type );
1223 }
1224
1225 /**
1226 * Query the DB and get a the child id's of public children
1227 *
1228 * @param int $parent_id Parent id
1229 * @param string $post_type Post type. Defaults to 'post'
1230 * @uses bbp_get_topic_post_type() To get the topic post type
1231 * @uses wp_cache_get() To check if there is a cache of the children
1232 * @uses wpdb::prepare() To prepare the query
1233 * @uses wpdb::get_col() To get the result of the query in an array
1234 * @uses wp_cache_set() To set the cache for future use
1235 * @uses apply_filters() Calls 'bbp_get_public_child_ids' with the child ids,
1236 * parent id and post type
1237 * @return array The array of children
1238 */
1239 function bbp_get_public_child_ids( $parent_id = 0, $post_type = 'post' ) {
1240 global $wpdb;
1241
1242 // Bail if nothing passed
1243 if ( empty( $parent_id ) )
1244 return false;
1245
1246 // The ID of the cached query
1247 $cache_id = 'bbp_parent_public_' . $parent_id . '_type_' . $post_type . '_child_ids';
1248 $post_status = array( bbp_get_public_status_id() );
1249
1250 // Add closed status if topic post type
1251 if ( $post_type == bbp_get_topic_post_type() )
1252 $post_status[] = bbp_get_closed_status_id();
1253
1254 // Join post statuses together
1255 $post_status = "'" . join( "', '", $post_status ) . "'";
1256
1257 // Check for cache and set if needed
1258 if ( !$child_ids = wp_cache_get( $cache_id, 'bbpress' ) ) {
1259 $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 ) );
1260 wp_cache_set( $cache_id, $child_ids, 'bbpress' );
1261 }
1262
1263 // Filter and return
1264 return apply_filters( 'bbp_get_public_child_ids', $child_ids, (int) $parent_id, $post_type );
1265 }
1266 /**
1267 * Query the DB and get a the child id's of all children
1268 *
1269 * @param int $parent_id Parent id
1270 * @param string $post_type Post type. Defaults to 'post'
1271 * @uses bbp_get_topic_post_type() To get the topic post type
1272 * @uses wp_cache_get() To check if there is a cache of the children
1273 * @uses wpdb::prepare() To prepare the query
1274 * @uses wpdb::get_col() To get the result of the query in an array
1275 * @uses wp_cache_set() To set the cache for future use
1276 * @uses apply_filters() Calls 'bbp_get_public_child_ids' with the child ids,
1277 * parent id and post type
1278 * @return array The array of children
1279 */
1280 function bbp_get_all_child_ids( $parent_id = 0, $post_type = 'post' ) {
1281 global $wpdb;
1282
1283 // Bail if nothing passed
1284 if ( empty( $parent_id ) )
1285 return false;
1286
1287 // The ID of the cached query
1288 $cache_id = 'bbp_parent_all_' . $parent_id . '_type_' . $post_type . '_child_ids';
1289 $post_status = array( bbp_get_public_status_id() );
1290
1291 // Extra post statuses based on post type
1292 switch ( $post_type ) {
1293
1294 // Forum
1295 case bbp_get_forum_post_type() :
1296 $post_status[] = bbp_get_private_status_id();
1297 $post_status[] = bbp_get_hidden_status_id();
1298 break;
1299
1300 // Topic
1301 case bbp_get_topic_post_type() :
1302 $post_status[] = bbp_get_closed_status_id();
1303 $post_status[] = bbp_get_trash_status_id();
1304 $post_status[] = bbp_get_spam_status_id();
1305 break;
1306
1307 // Reply
1308 case bbp_get_reply_post_type() :
1309 $post_status[] = bbp_get_trash_status_id();
1310 $post_status[] = bbp_get_spam_status_id();
1311 break;
1312 }
1313
1314 // Join post statuses together
1315 $post_status = "'" . join( "', '", $post_status ) . "'";
1316
1317 // Check for cache and set if needed
1318 if ( !$child_ids = wp_cache_get( $cache_id, 'bbpress' ) ) {
1319 $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 ) );
1320 wp_cache_set( $cache_id, $child_ids, 'bbpress' );
1321 }
1322
1323 // Filter and return
1324 return apply_filters( 'bbp_get_all_child_ids', $child_ids, (int) $parent_id, $post_type );
1325 }
1326
1327 /** Feeds *********************************************************************/
1328
1329 /**
1330 * This function is hooked into the WordPress 'request' action and is
1331 * responsible for sniffing out the query vars and serving up RSS2 feeds if
1332 * the stars align and the user has requested a feed of any bbPress type.
1333 *
1334 * @since bbPress (r3171)
1335 *
1336 * @global WP_Query $wp_query
1337 * @param array $query_vars
1338 * @return array
1339 */
1340 function bbp_request_feed_trap( $query_vars ) {
1341 global $wp_query;
1342
1343 // Looking at a feed
1344 if ( isset( $query_vars['feed'] ) ) {
1345
1346 // Forum Feed
1347 if ( isset( $query_vars['post_type'] ) ) {
1348
1349 // What bbPress post type are we looking for feeds on?
1350 switch ( $query_vars['post_type'] ) {
1351
1352 // Forum
1353 case bbp_get_forum_post_type() :
1354
1355 // Declare local variable(s)
1356 $meta_query = array();
1357
1358 // Single forum
1359 if ( isset( $query_vars[bbp_get_forum_post_type()] ) ) {
1360
1361 // Get the forum by the path
1362 $forum = get_page_by_path( $query_vars[bbp_get_forum_post_type()], OBJECT, bbp_get_forum_post_type() );
1363 $forum_id = $forum->ID;
1364
1365 // Load up our own query
1366 $wp_query = new WP_Query( array(
1367 'post_type' => bbp_get_forum_post_type(),
1368 'ID' => $forum_id
1369 ) );
1370
1371 // Restrict to specific forum ID
1372 $meta_query = array( array(
1373 'key' => '_bbp_forum_id',
1374 'value' => $forum_id,
1375 'compare' => '='
1376 ) );
1377 }
1378
1379 // Only forum replies
1380 if ( !empty( $_GET['type'] ) && ( bbp_get_reply_post_type() == $_GET['type'] ) ) {
1381
1382 // The query
1383 $the_query = array(
1384 'author' => 0,
1385 'post_type' => bbp_get_reply_post_type(),
1386 'post_parent' => 'any',
1387 'post_status' => join( ',', array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ),
1388 'posts_per_page' => get_option( '_bbp_replies_per_rss_page', 25 ),
1389 'order' => 'DESC',
1390 'meta_query' => $meta_query
1391 );
1392
1393 // Output the feed
1394 bbp_display_replies_feed_rss2( $the_query );
1395
1396 // Only forum topics
1397 } elseif ( !empty( $_GET['type'] ) && ( bbp_get_topic_post_type() == $_GET['type'] ) ) {
1398
1399 // The query
1400 $the_query = array(
1401 'author' => 0,
1402 'post_type' => bbp_get_topic_post_type(),
1403 'post_parent' => 'any',
1404 'post_status' => join( ',', array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ),
1405 'posts_per_page' => get_option( '_bbp_topics_per_rss_page', 25 ),
1406 'order' => 'DESC',
1407 'meta_query' => $meta_query
1408 );
1409
1410 // Output the feed
1411 bbp_display_topics_feed_rss2( $the_query );
1412
1413 // All forum topics and replies
1414 } else {
1415
1416 // The query
1417 $the_query = array(
1418 'author' => 0,
1419 'post_type' => array( bbp_get_reply_post_type(), bbp_get_topic_post_type() ),
1420 'post_parent' => 'any',
1421 'post_status' => join( ',', array( bbp_get_public_status_id(), bbp_get_closed_status_id() ) ),
1422 'posts_per_page' => get_option( '_bbp_replies_per_rss_page', 25 ),
1423 'order' => 'DESC',
1424 'meta_query' => $meta_query
1425 );
1426
1427 // Output the feed
1428 bbp_display_replies_feed_rss2( $the_query );
1429 }
1430
1431 break;
1432
1433 // Topic feed - Show replies
1434 case bbp_get_topic_post_type() :
1435
1436 // Single topic
1437 if ( isset( $query_vars[bbp_get_topic_post_type()] ) ) {
1438
1439 // Load up our own query
1440 $wp_query = new WP_Query( array(
1441 'post_type' => bbp_get_topic_post_type(),
1442 'name' => $query_vars[bbp_get_topic_post_type()]
1443 ) );
1444
1445 // Output the feed
1446 bbp_display_replies_feed_rss2();
1447
1448 // All topics
1449 } else {
1450
1451 // The query
1452 $the_query = array(
1453 'author' => 0,
1454 'post_parent' => 'any',
1455 'posts_per_page' => get_option( '_bbp_topics_per_rss_page', 25 ),
1456 'show_stickies' => false,
1457 );
1458
1459 // Output the feed
1460 bbp_display_topics_feed_rss2( $the_query );
1461 }
1462
1463 break;
1464
1465 // Replies
1466 case bbp_get_reply_post_type() :
1467
1468 // The query
1469 $the_query = array(
1470 'posts_per_page' => get_option( '_bbp_replies_per_rss_page', 25 ),
1471 'meta_query' => array( array( ) )
1472 );
1473
1474 // All replies
1475 if ( !isset( $query_vars[bbp_get_reply_post_type()] ) ) {
1476 bbp_display_replies_feed_rss2( $the_query );
1477 }
1478
1479 break;
1480 }
1481 }
1482 }
1483
1484 // No feed so continue on
1485 return $query_vars;
1486 }
1487
1488 /** Errors ********************************************************************/
1489
1490 /**
1491 * Adds an error message to later be output in the theme
1492 *
1493 * @since bbPress (r3381)
1494 *
1495 * @global bbPress $bbp
1496 *
1497 * @see WP_Error()
1498 * @uses WP_Error::add();
1499 *
1500 * @param string $code Unique code for the error message
1501 * @param string $message Translated error message
1502 * @param string $data Any additional data passed with the error message
1503 */
1504 function bbp_add_error( $code = '', $message = '', $data = '' ) {
1505 global $bbp;
1506
1507 $bbp->errors->add( $code, $message, $data );
1508 }
1509
1510 /**
1511 * Check if error messages exist in queue
1512 *
1513 * @since bbPress (r3381)
1514 *
1515 * @global bbPress $bbp
1516 *
1517 * @see WP_Error()
1518 *
1519 * @uses is_wp_error()
1520 * @usese WP_Error::get_error_codes()
1521 */
1522 function bbp_has_errors() {
1523 global $bbp;
1524
1525 // Assume no errors
1526 $has_errors = false;
1527
1528 // Check for errors
1529 if ( $bbp->errors->get_error_codes() )
1530 $has_errors = true;
1531
1532 // Filter return value
1533 $has_errors = apply_filters( 'bbp_has_errors', $has_errors, $bbp->errors );
1534
1535 return $has_errors;
1536 }
1537
1538 /** Post Statuses *************************************************************/
1539
1540 /**
1541 * Return the public post status ID
1542 *
1543 * @since bbPress (r3504)
1544 *
1545 * @global bbPress $bbp
1546 * @return string
1547 */
1548 function bbp_get_public_status_id() {
1549 global $bbp;
1550 return $bbp->public_status_id;
1551 }
1552
1553 /**
1554 * Return the private post status ID
1555 *
1556 * @since bbPress (r3504)
1557 *
1558 * @global bbPress $bbp
1559 * @return string
1560 */
1561 function bbp_get_private_status_id() {
1562 global $bbp;
1563 return $bbp->private_status_id;
1564 }
1565
1566 /**
1567 * Return the hidden post status ID
1568 *
1569 * @since bbPress (r3504)
1570 *
1571 * @global bbPress $bbp
1572 * @return string
1573 */
1574 function bbp_get_hidden_status_id() {
1575 global $bbp;
1576 return $bbp->hidden_status_id;
1577 }
1578
1579 /**
1580 * Return the closed post status ID
1581 *
1582 * @since bbPress (r3504)
1583 *
1584 * @global bbPress $bbp
1585 * @return string
1586 */
1587 function bbp_get_closed_status_id() {
1588 global $bbp;
1589 return $bbp->closed_status_id;
1590 }
1591
1592 /**
1593 * Return the spam post status ID
1594 *
1595 * @since bbPress (r3504)
1596 *
1597 * @global bbPress $bbp
1598 * @return string
1599 */
1600 function bbp_get_spam_status_id() {
1601 global $bbp;
1602 return $bbp->spam_status_id;
1603 }
1604
1605 /**
1606 * Return the trash post status ID
1607 *
1608 * @since bbPress (r3504)
1609 *
1610 * @global bbPress $bbp
1611 * @return string
1612 */
1613 function bbp_get_trash_status_id() {
1614 global $bbp;
1615 return $bbp->trash_status_id;
1616 }
1617
1618 /**
1619 * Return the orphan post status ID
1620 *
1621 * @since bbPress (r3504)
1622 *
1623 * @global bbPress $bbp
1624 * @return string
1625 */
1626 function bbp_get_orphan_status_id() {
1627 global $bbp;
1628 return $bbp->orphan_status_id;
1629 }
1630
1631 ?>
1632