PluginProbe
bbPress / trunk
bbPress vtrunk
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 2.2.2 All 71 releases
bbpress / includes / users / functions.php

functions.php in bbPress trunk, at includes/users/functions.php

1,028 lines 28.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * bbPress User Functions.
5 *
6 * @package bbPress
7 * @subpackage Functions
8 */
9
10 // Exit if accessed directly
11 defined( 'ABSPATH' ) || exit;
12
13 /**
14 * Redirect back to $url when attempting to use the login page.
15 *
16 * @since 2.0.0 bbPress (r2815)
17 *
18 * @param string $url The url.
19 * @param string $raw_url Raw url.
20 * @param object $user User object.
21 */
22 function bbp_redirect_login( $url = '', $raw_url = '', $user = '' ) {
23
24 // Raw redirect_to was passed, so use it
25 if ( ! empty( $raw_url ) ) {
26 $url = $raw_url;
27
28 // $url was manually set in wp-login.php to redirect to admin
29 } elseif ( admin_url() === $url ) {
30 $url = home_url();
31
32 // $url is empty
33 } elseif ( empty( $url ) ) {
34 $url = home_url();
35 }
36
37 // Filter & return
38 return apply_filters( 'bbp_redirect_login', $url, $raw_url, $user );
39 }
40
41 /**
42 * Is an anonymous topic/reply being made?
43 *
44 * @since 2.0.0 bbPress (r2688)
45 *
46 * @return bool True if anonymous is allowed and user is not logged in, false if
47 * anonymous is not allowed or user is logged in.
48 */
49 function bbp_is_anonymous() {
50 $is_anonymous = ( ! is_user_logged_in() && bbp_allow_anonymous() );
51
52 // Filter & return
53 return (bool) apply_filters( 'bbp_is_anonymous', $is_anonymous );
54 }
55
56 /**
57 * Echoes the values for current poster (uses WP comment cookies).
58 *
59 * @since 2.0.0 bbPress (r2734)
60 *
61 * @param string $key Which value to echo?
62 */
63 function bbp_current_anonymous_user_data( $key = '' ) {
64 echo esc_attr( bbp_get_current_anonymous_user_data( $key ) );
65 }
66
67 /**
68 * Get the cookies for current poster (uses WP comment cookies).
69 *
70 * @since 2.0.0 bbPress (r2734)
71 *
72 * @param string $key Optional. Which value to get? If not given, then
73 * an array is returned.
74 * @return string|array Cookie(s) for current poster.
75 */
76 function bbp_get_current_anonymous_user_data( $key = '' ) {
77
78 // Array of allowed cookie names
79 $cookie_names = array(
80 'name' => 'comment_author',
81 'email' => 'comment_author_email',
82 'url' => 'comment_author_url',
83
84 // Here just for the sake of them, use the above ones
85 'comment_author' => 'comment_author',
86 'comment_author_email' => 'comment_author_email',
87 'comment_author_url' => 'comment_author_url',
88 );
89
90 // Get the current poster's info from the cookies
91 $bbp_current_poster = wp_get_current_commenter();
92
93 // Sanitize the cookie key being retrieved
94 $key = sanitize_key( $key );
95
96 // Maybe return a specific key
97 if ( ! empty( $key ) && in_array( $key, array_keys( $cookie_names ), true ) ) {
98 return $bbp_current_poster[ $cookie_names[ $key ] ];
99 }
100
101 // Return all keys
102 return $bbp_current_poster;
103 }
104
105 /**
106 * Set the cookies for current poster (uses WP comment cookies).
107 *
108 * @since 2.0.0 bbPress (r2734)
109 *
110 * @param array $anonymous_data Optional - if it's an anonymous post. Do not
111 * supply if supplying $author_id. Should be
112 * sanitized (see {@link bbp_filter_anonymous_post_data()}.
113 */
114 function bbp_set_current_anonymous_user_data( $anonymous_data = array() ) {
115
116 // Bail if empty or not an array
117 if ( empty( $anonymous_data ) || ! is_array( $anonymous_data ) ) {
118 return;
119 }
120
121 // Setup cookie expiration
122 $lifetime = (int) apply_filters( 'comment_cookie_lifetime', 30000000 );
123 $expiry = time() + $lifetime;
124 $secure = ( 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME ) );
125
126 // Set the cookies
127 setcookie( 'comment_author_' . COOKIEHASH, $anonymous_data['bbp_anonymous_name'], $expiry, COOKIEPATH, COOKIE_DOMAIN, $secure );
128 setcookie( 'comment_author_email_' . COOKIEHASH, $anonymous_data['bbp_anonymous_email'], $expiry, COOKIEPATH, COOKIE_DOMAIN, $secure );
129 setcookie( 'comment_author_url_' . COOKIEHASH, $anonymous_data['bbp_anonymous_website'], $expiry, COOKIEPATH, COOKIE_DOMAIN, $secure );
130 }
131
132 /**
133 * Get the poster IP address.
134 *
135 * @since 2.0.0 bbPress (r3120)
136 * @since 2.6.0 bbPress (r5609) Added `empty()` check for unit tests
137 *
138 * @return string
139 */
140 function bbp_current_author_ip() {
141
142 // Check for remote address
143 $remote_address = ! empty( $_SERVER['REMOTE_ADDR'] )
144 ? wp_unslash( $_SERVER['REMOTE_ADDR'] )
145 : '127.0.0.1';
146
147 // Remove any unsavory bits
148 $retval = preg_replace( '/[^0-9a-fA-F:., ]/', '', $remote_address );
149
150 // Filter & return
151 return apply_filters( 'bbp_current_author_ip', $retval, $remote_address );
152 }
153
154 /**
155 * Get the poster user agent.
156 *
157 * @since 2.0.0 bbPress (r3446)
158 *
159 * @return string
160 */
161 function bbp_current_author_ua() {
162 $retval = ! empty( $_SERVER['HTTP_USER_AGENT'] )
163 ? mb_substr( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ), 0, 254 )
164 : '';
165
166 // Filter & return
167 return apply_filters( 'bbp_current_author_ua', $retval );
168 }
169
170 /** Edit **********************************************************************/
171
172 /**
173 * Handles the front end user editing from POST requests.
174 *
175 * @since 2.0.0 bbPress (r2790)
176 *
177 * @param string $action The requested action to compare this function to.
178 */
179 function bbp_edit_user_handler( $action = '' ) {
180
181 // Bail if action is not `bbp-update-user`
182 if ( 'bbp-update-user' !== $action ) {
183 return;
184 }
185
186 // Bail if in wp-admin
187 if ( is_admin() ) {
188 return;
189 }
190
191 // Get the displayed user ID
192 $user_id = bbp_get_displayed_user_id();
193
194 // Request check
195 if ( ! bbp_is_user_profile_form_post_request( $user_id ) ) {
196 bbp_add_error( 'bbp_update_user_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
197 return;
198 }
199
200 // Cap check
201 if ( ! current_user_can( 'edit_user', $user_id ) ) {
202 bbp_add_error( 'bbp_update_user_capability', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
203 return;
204 }
205
206 // Empty email check
207 if ( empty( $_POST['email'] ) ) {
208 bbp_add_error( 'bbp_user_email_empty', __( '<strong>Error</strong>: That is not a valid email address.', 'bbpress' ), array( 'form-field' => 'email' ) );
209 return;
210 }
211
212 // Get the users current email address to use for comparisons
213 $user_email = bbp_get_displayed_user_field( 'user_email', 'raw' );
214
215 // Bail if no email change
216 if ( $user_email !== $_POST['email'] ) {
217
218 // Check that new email address is valid
219 if ( ! is_email( $_POST['email'] ) ) {
220 bbp_add_error( 'bbp_user_email_invalid', __( '<strong>Error</strong>: That is not a valid email address.', 'bbpress' ), array( 'form-field' => 'email' ) );
221 return;
222 }
223
224 // Check if email address is already in use
225 if ( email_exists( $_POST['email'] ) ) {
226 bbp_add_error( 'bbp_user_email_taken', __( '<strong>Error</strong>: That email address is already in use.', 'bbpress' ), array( 'form-field' => 'email' ) );
227 return;
228 }
229
230 // Update the option
231 $option = array(
232 'hash' => md5( $_POST['email'] . time() . wp_rand() ),
233 'newemail' => $_POST['email'],
234 );
235 update_user_meta( $user_id, '_new_email', $option );
236
237 // Attempt to notify the user of email address change
238 bbp_edit_user_email_send_notification( $user_id, $option );
239
240 // Set the POST email variable back to the user's email address
241 // so `edit_user()` does not attempt to update it. This is not ideal,
242 // but it's also what send_confirmation_on_profile_email() does.
243 $_POST['email'] = $user_email;
244 }
245
246 // Do action based on who's profile you're editing
247 $edit_action = bbp_is_user_home_edit()
248 ? 'personal_options_update'
249 : 'edit_user_profile_update';
250
251 do_action( $edit_action, $user_id );
252
253 // Prevent edit_user() from wiping out the user's Toolbar on front setting
254 if ( ! isset( $_POST['admin_bar_front'] ) && _get_admin_bar_pref( 'front', $user_id ) ) {
255 $_POST['admin_bar_front'] = 1;
256 }
257
258 // Bail if errors already exist
259 if ( bbp_has_errors() ) {
260 return;
261 }
262
263 // Handle user edit
264 $edit_user = edit_user( $user_id );
265
266 // Error(s) editing the user, so copy them into the global.
267 if ( is_wp_error( $edit_user ) ) {
268 bbpress()->errors = $edit_user;
269
270 // Successful edit to redirect
271 } elseif ( is_integer( $edit_user ) ) {
272
273 // Maybe update super admin ability
274 if ( is_multisite() && ! bbp_is_user_home_edit() && current_user_can( 'manage_network_options' ) && is_super_admin() ) {
275 empty( $_POST['super_admin'] )
276 ? revoke_super_admin( $edit_user )
277 : grant_super_admin( $edit_user );
278 }
279
280 // Redirect
281 $args = array( 'updated' => 'true' );
282 $user_url = bbp_get_user_profile_edit_url( $edit_user );
283 $redirect = add_query_arg( $args, $user_url );
284
285 bbp_redirect( $redirect );
286 }
287 }
288
289 /**
290 * Handles user email address updating from GET requests.
291 *
292 * @since 2.6.0 bbPress (r5660)
293 *
294 * @param string $action
295 */
296 function bbp_user_email_change_handler( $action = '' ) {
297
298 // Bail if action is not `bbp-update-user-email`
299 if ( 'bbp-update-user-email' !== $action ) {
300 return;
301 }
302
303 // Bail if not on users own profile
304 if ( ! bbp_is_user_home_edit() ) {
305 return;
306 }
307
308 // Bail if not attempting to modify user email address
309 if ( empty( $_GET['newuseremail'] ) && empty( $_GET['dismiss'] ) ) {
310 return;
311 }
312
313 // Get the displayed user ID & option key
314 $user_id = bbp_get_displayed_user_id();
315 $key = '_new_email';
316 $redirect_to = bbp_get_user_profile_edit_url( $user_id );
317
318 // Execute confirmed email change.
319 if ( ! empty( $_GET['newuseremail'] ) ) {
320
321 // Check for email address change option
322 $new_email = get_user_meta( $user_id, $key, true );
323
324 // Redirect if *no* email address change exists
325 if ( false === $new_email ) {
326 bbp_redirect( $redirect_to );
327 }
328
329 // Cleanup & redirect if *invalid* email address change exists
330 if ( empty( $new_email['hash'] ) || empty( $new_email['newemail'] ) ) {
331 delete_user_meta( $user_id, $key );
332
333 bbp_redirect( $redirect_to );
334 }
335
336 // Compare hashes, and update user if hashes match
337 if ( hash_equals( $new_email['hash'], $_GET['newuseremail'] ) ) {
338
339 // Does another user have this email address already?
340 if ( email_exists( $new_email['newemail'] ) ) {
341 delete_user_meta( $user_id, $key );
342
343 bbp_add_error( 'bbp_user_email_taken', __( '<strong>Error</strong>: That email address is already in use.', 'bbpress' ), array( 'form-field' => 'email' ) );
344
345 // Email address is good to change to
346 } else {
347
348 // Create a stdClass (for easy call to wp_update_user())
349 $user = new stdClass();
350 $user->ID = $user_id;
351 $user->user_email = esc_html( trim( $new_email['newemail'] ) );
352
353 // Attempt to update user email
354 $update_user = wp_update_user( $user );
355
356 // Error(s) editing the user, so copy them into the global
357 if ( is_wp_error( $update_user ) ) {
358 bbpress()->errors = $update_user;
359
360 // All done, so redirect and show the updated message
361 } else {
362
363 // Update signups table, if signups table & entry exists
364 // For Multisite & BuddyPress compatibility
365 $bbp_db = bbp_db();
366 if ( ! empty( $bbp_db->signups ) && $bbp_db->get_var( $bbp_db->prepare( "SELECT user_login FROM {$bbp_db->signups} WHERE user_login = %s", bbp_get_displayed_user_field( 'user_login', 'raw' ) ) ) ) {
367 $bbp_db->query( $bbp_db->prepare( "UPDATE {$bbp_db->signups} SET user_email = %s WHERE user_login = %s", $user->user_email, bbp_get_displayed_user_field( 'user_login', 'raw' ) ) );
368 }
369
370 delete_user_meta( $user_id, $key );
371
372 bbp_redirect( add_query_arg( array( 'updated' => 'true' ), $redirect_to ) );
373 }
374 }
375 }
376
377 // Delete new email address from user options
378 } elseif ( ! empty( $_GET['dismiss'] ) && ( "{$user_id}{$key}" === $_GET['dismiss'] ) ) {
379 if ( ! bbp_verify_nonce_request( "dismiss-{$user_id}{$key}" ) ) {
380 bbp_add_error( 'bbp_dismiss_new_email_nonce', __( '<strong>Error</strong>: Are you sure you wanted to do that?', 'bbpress' ) );
381 return;
382 }
383
384 delete_user_meta( $user_id, $key );
385 bbp_redirect( $redirect_to );
386 }
387 }
388
389 /**
390 * Sends an email when an email address change occurs on POST requests.
391 *
392 * @since 2.6.0 bbPress (r5660)
393 *
394 * @see send_confirmation_on_profile_email()
395 */
396 function bbp_edit_user_email_send_notification( $user_id = 0, $args = array() ) {
397
398 // Parse args
399 $r = bbp_parse_args(
400 $args,
401 array(
402 'hash' => '',
403 'newemail' => '',
404 )
405 );
406
407 // Bail if any relevant parameters are empty
408 if ( empty( $user_id ) || empty( $r['hash'] ) || empty( $r['newemail'] ) ) {
409 bbp_add_error( 'bbp_user_email_invalid_hash', __( '<strong>Error</strong>: An error occurred while updating your email address.', 'bbpress' ), array( 'form-field' => 'email' ) );
410 return;
411 }
412
413 // Build the nonced URL to dismiss the pending change
414 $user_login = bbp_get_displayed_user_field( 'user_login', 'raw' );
415 $user_url = bbp_get_user_profile_edit_url( $user_id );
416 $confirm_url = add_query_arg(
417 array(
418 'action' => 'bbp-update-user-email',
419 'newuseremail' => $r['hash']
420 ),
421 $user_url
422 );
423
424 /* translators: 1: Username, 2: Confirmation URL, 3: New email address, 4: Site name, 5: Site URL */
425 $email_text = __(
426 '%1$s
427
428 Someone requested a change to the email address on your account.
429
430 Please click the following link to confirm this change:
431 %2$s
432
433 If you did not request this, you can safely ignore and delete this notification.
434
435 This email was sent to: %3$s
436
437 Regards,
438 The %4$s Team
439 %5$s',
440 'bbpress'
441 );
442
443 /**
444 * Filter the email text sent when a user changes emails.
445 *
446 * The following strings have a special meaning and will get replaced dynamically:
447 *
448 * %1$s - The current user's username
449 * %2$s - The link to click on to confirm the email change
450 * %3$s - The new email
451 * %4$s - The name of the site
452 * %5$s - The URL to the site
453 *
454 * @param string $email_text Text in the email.
455 * @param string $r New user email that the current user has changed to.
456 */
457 $content = apply_filters( 'bbp_user_email_update_content', $email_text, $r );
458
459 // Build the email message
460 $message = sprintf( $content, $user_login, $confirm_url, $r['newemail'], get_site_option( 'site_name' ), network_home_url() );
461
462 // Build the email subject
463 /* translators: %s: Site name */
464 $subject = sprintf( __( '[%s] New Email Address', 'bbpress' ), wp_specialchars_decode( get_option( 'blogname' ) ) );
465
466 // Send the email
467 wp_mail( $r['newemail'], $subject, $message );
468 }
469
470 /**
471 * Conditionally hook the core WordPress output actions to the end of the
472 * default user's edit profile template.
473 *
474 * This allows clever plugin authors to conditionally unhook the WordPress core
475 * output actions if they don't want any unexpected junk to appear there, and
476 * also avoids needing to pollute the templates with additional logic and actions.
477 *
478 * @since 2.2.0 bbPress (r4273)
479 */
480 function bbp_user_edit_after() {
481 $action = bbp_is_user_home_edit() ? 'show_user_profile' : 'edit_user_profile';
482
483 do_action( $action, get_userdata( bbp_get_displayed_user_id() ) );
484 }
485
486 /** User Queries **************************************************************/
487
488 /**
489 * Get the topics that a user created.
490 *
491 * @since 2.0.0 bbPress (r2660)
492 * @since 2.6.0 bbPress (r6618) Signature changed to accept an array of arguments
493 *
494 * @param array $args Optional. Arguments to pass into bbp_has_topics().
495 *
496 * @return bool True if user has started topics, otherwise false.
497 */
498 function bbp_get_user_topics_started( $args = array() ) {
499
500 // Backwards compat for pre-2.6.0
501 if ( is_numeric( $args ) ) {
502 $args = array(
503 'author' => bbp_get_user_id( $args, false, false )
504 );
505 }
506
507 // Default arguments
508 $defaults = array(
509 'author' => bbp_get_displayed_user_id()
510 );
511
512 // Parse arguments
513 $r = bbp_parse_args( $args, $defaults, 'get_user_topics_started' );
514
515 // Get the topics
516 $query = bbp_has_topics( $r );
517 $user_id = $r['author'];
518
519 // Filter & return
520 return apply_filters( 'bbp_get_user_topics_started', $query, $user_id, $r, $args );
521 }
522
523 /**
524 * Get the replies that a user created.
525 *
526 * @since 2.2.0 bbPress (r4225)
527 * @since 2.6.0 bbPress (r6618) Signature changed to accept an array of arguments
528 *
529 * @param array $args Optional. Arguments to pass into bbp_has_replies().
530 *
531 * @return bool True if user has created replies, otherwise false.
532 */
533 function bbp_get_user_replies_created( $args = array() ) {
534
535 // Backwards compat for pre-2.6.0
536 if ( is_numeric( $args ) ) {
537 $args = array(
538 'author' => bbp_get_user_id( $args, false, false ),
539 'post_type' => bbp_get_reply_post_type(),
540 'order' => 'DESC'
541 );
542 }
543
544 // Default arguments
545 $defaults = array(
546 'author' => bbp_get_displayed_user_id(),
547 'post_type' => bbp_get_reply_post_type(),
548 'order' => 'DESC'
549 );
550
551 // Parse arguments
552 $r = bbp_parse_args( $args, $defaults, 'get_user_replies_created' );
553
554 // Get the replies
555 $query = bbp_has_replies( $r );
556 $user_id = $r['author'];
557
558 // Filter & return
559 return apply_filters( 'bbp_get_user_replies_created', $query, $user_id, $r, $args );
560 }
561
562 /**
563 * Get user IDs from nicenames.
564 *
565 * This function is primarily used when saving object moderators.
566 *
567 * @since 2.6.0 bbPress
568 *
569 * @param mixed $user_nicenames
570 * @return array
571 */
572 function bbp_get_user_ids_from_nicenames( $user_nicenames = array() ) {
573
574 // Default value
575 $retval = array();
576
577 // Only query if nicenames
578 if ( ! empty( $user_nicenames ) ) {
579
580 // Maybe explode by comma
581 $user_nicenames = ( is_string( $user_nicenames ) && strstr( $user_nicenames, ',' ) )
582 ? explode( ',', $user_nicenames )
583 : (array) $user_nicenames;
584
585 // Sanitize each nicename in the array
586 $user_nicenames = array_map( 'sanitize_title', $user_nicenames );
587
588 // Get users
589 $users = get_users(
590 array(
591 'nicename__in' => $user_nicenames
592 )
593 );
594
595 // Pluck or empty
596 if ( ! empty( $users ) ) {
597 $retval = wp_list_pluck( $users, 'ID' );
598 }
599 }
600
601 // Filter & return
602 return (array) apply_filters( 'bbp_get_user_ids_from_nicenames', $retval, $user_nicenames );
603 }
604
605 /**
606 * Get user nicenames from IDs.
607 *
608 * This function is primarily used when saving object moderators.
609 *
610 * @since 2.6.0 bbPress
611 *
612 * @param mixed $user_ids User ids.
613 * @return array
614 */
615 function bbp_get_user_nicenames_from_ids( $user_ids = array() ) {
616
617 // Default value
618 $retval = array();
619
620 // Only query if nicenames
621 if ( ! empty( $user_ids ) ) {
622
623 // Get users
624 $users = get_users(
625 array(
626 'include' => $user_ids
627 )
628 );
629
630 // Pluck or empty
631 if ( ! empty( $users ) ) {
632 $retval = wp_list_pluck( $users, 'user_nicename' );
633 }
634 }
635
636 // Filter & return
637 return (array) apply_filters( 'bbp_get_user_nicenames_from_ids', $retval, $user_ids );
638 }
639
640 /** Post Counts ***************************************************************/
641
642 /**
643 * Return the raw database count of topics by a user.
644 *
645 * @since 2.1.0 bbPress (r3633)
646 *
647 * @param int $user_id User ID to get count for.
648 *
649 * @return int Raw DB count of topics.
650 */
651 function bbp_get_user_topic_count_raw( $user_id = 0 ) {
652 $user_id = bbp_get_user_id( $user_id );
653 $bbp_db = bbp_db();
654 $statii = "'" . implode( "', '", bbp_get_public_topic_statuses() ) . "'";
655 $sql = "SELECT COUNT(*)
656 FROM {$bbp_db->posts}
657 WHERE post_author = %d
658 AND post_type = %s
659 AND post_status IN ({$statii})";
660
661 $query = $bbp_db->prepare( $sql, $user_id, bbp_get_topic_post_type() );
662 $count = (int) $bbp_db->get_var( $query );
663
664 // Filter & return
665 return (int) apply_filters( 'bbp_get_user_topic_count_raw', $count, $user_id );
666 }
667
668 /**
669 * Return the raw database count of replies by a user.
670 *
671 * @since 2.1.0 bbPress (r3633)
672 *
673 * @param int $user_id User ID to get count for.
674 *
675 * @return int Raw DB count of replies.
676 */
677 function bbp_get_user_reply_count_raw( $user_id = 0 ) {
678 $user_id = bbp_get_user_id( $user_id );
679 $bbp_db = bbp_db();
680 $statii = "'" . implode( "', '", bbp_get_public_reply_statuses() ) . "'";
681 $sql = "SELECT COUNT(*)
682 FROM {$bbp_db->posts}
683 WHERE post_author = %d
684 AND post_type = %s
685 AND post_status IN ({$statii})";
686
687 $query = $bbp_db->prepare( $sql, $user_id, bbp_get_reply_post_type() );
688 $count = (int) $bbp_db->get_var( $query );
689
690 // Filter & return
691 return (int) apply_filters( 'bbp_get_user_reply_count_raw', $count, $user_id );
692 }
693
694 /**
695 * Bump the topic count for a user by a certain amount.
696 *
697 * @since 2.6.0 bbPress (r5309)
698 *
699 * @param int $user_id User id.
700 * @param int $difference Optional. Default 1. Number to bump.
701 */
702 function bbp_bump_user_topic_count( $user_id = 0, $difference = 1 ) {
703
704 // Bail if no bump
705 if ( empty( $difference ) ) {
706 return false;
707 }
708
709 // Validate user ID
710 $user_id = bbp_get_user_id( $user_id );
711 if ( empty( $user_id ) ) {
712 return false;
713 }
714
715 // Check meta for count, or query directly if not found
716 $count = bbp_get_user_topic_count( $user_id, true );
717 if ( empty( $count ) ) {
718 $count = bbp_get_user_topic_count_raw( $user_id );
719 }
720
721 $difference = (int) $difference;
722 $user_topic_count = (int) ( $count + $difference );
723
724 // Add them up and filter them
725 $new_count = (int) apply_filters( 'bbp_bump_user_topic_count', $user_topic_count, $user_id, $difference, $count );
726
727 return bbp_update_user_topic_count( $user_id, $new_count );
728 }
729
730 /**
731 * Bump the reply count for a user by a certain amount.
732 *
733 * @since 2.6.0 bbPress (r5309)
734 *
735 * @param int $user_id User id.
736 * @param int $difference Optional. Default 1. Number to bump.
737 */
738 function bbp_bump_user_reply_count( $user_id = 0, $difference = 1 ) {
739
740 // Bail if no bump
741 if ( empty( $difference ) ) {
742 return false;
743 }
744
745 // Validate user ID
746 $user_id = bbp_get_user_id( $user_id );
747 if ( empty( $user_id ) ) {
748 return false;
749 }
750
751 // Check meta for count, or query directly if not found
752 $count = bbp_get_user_reply_count( $user_id, true );
753 if ( empty( $count ) ) {
754 $count = bbp_get_user_reply_count_raw( $user_id );
755 }
756
757 $difference = (int) $difference;
758 $user_reply_count = (int) ( $count + $difference );
759
760 // Add them up and filter them
761 $new_count = (int) apply_filters( 'bbp_bump_user_reply_count', $user_reply_count, $user_id, $difference, $count );
762
763 return bbp_update_user_reply_count( $user_id, $new_count );
764 }
765
766 /**
767 * Helper function used to increase (by one) the count of topics for a user when
768 * a topic is published.
769 *
770 * @since 2.6.0 bbPress (r5309)
771 *
772 * @access
773 * @param $topic_id
774 * @param $forum_id
775 * @param $anonymous_data
776 * @param $topic_author
777 */
778 function bbp_increase_user_topic_count( $topic_id = 0 ) {
779 $user_id = bbp_get_topic_author_id( $topic_id );
780 return bbp_bump_user_topic_count( $user_id, 1 );
781 }
782
783 /**
784 * Helper function used to increase (by one) the count of replies for a user when
785 * a reply is published.
786 *
787 * This is a helper function, hooked to `bbp_new_reply`.
788 *
789 * @since 2.6.0 bbPress (r5309)
790 *
791 * @param $topic_id
792 * @param $forum_id
793 * @param $anonymous_data
794 * @param $topic_author
795 */
796 function bbp_increase_user_reply_count( $reply_id = 0 ) {
797 $user_id = bbp_get_reply_author_id( $reply_id );
798 return bbp_bump_user_reply_count( $user_id, 1 );
799 }
800
801 /**
802 * Helper function used to decrease (by one) the count of topics for a user when
803 * a topic is unpublished.
804 *
805 * @since 2.6.0 bbPress (r5309)
806 *
807 * @param $topic_id
808 */
809 function bbp_decrease_user_topic_count( $topic_id = 0 ) {
810 $user_id = bbp_get_topic_author_id( $topic_id );
811 return bbp_bump_user_topic_count( $user_id, -1 );
812 }
813
814 /**
815 * Helper function used to increase (by one) the count of replies for a user when
816 * a topic is unpublished.
817 *
818 * @since 2.6.0 bbPress (r5309)
819 *
820 * @param $reply_id
821 */
822 function bbp_decrease_user_reply_count( $reply_id = 0 ) {
823 $user_id = bbp_get_reply_author_id( $reply_id );
824 return bbp_bump_user_reply_count( $user_id, -1 );
825 }
826
827 /** Permissions ***************************************************************/
828
829 /**
830 * Redirect if unauthorized user is attempting to edit another user.
831 *
832 * This is hooked to 'bbp_template_redirect' and controls the conditions under
833 * which a user can edit another user (or themselves.) If these conditions are
834 * met, we assume a user cannot perform this task, and look for ways they can
835 * earn the ability to access this template.
836 *
837 * @since 2.1.0 bbPress (r3605)
838 */
839 function bbp_check_user_edit() {
840
841 // Bail if not editing a user
842 if ( ! bbp_is_single_user_edit() ) {
843 return;
844 }
845
846 // Default to false
847 $redirect = true;
848 $user_id = bbp_get_displayed_user_id();
849
850 // Allow user to edit their own profile
851 if ( bbp_is_user_home_edit() ) {
852 $redirect = false;
853
854 // Allow if current user can edit the displayed user
855 } elseif ( current_user_can( 'edit_user', $user_id ) ) {
856 $redirect = false;
857
858 // Allow if user can manage network users, or edit-any is enabled
859 } elseif ( current_user_can( 'manage_network_users' ) || apply_filters( 'enable_edit_any_user_configuration', false ) ) {
860 $redirect = false;
861 }
862
863 // Allow conclusion to be overridden
864 $redirect = (bool) apply_filters( 'bbp_check_user_edit', $redirect, $user_id );
865
866 // Bail if not redirecting
867 if ( false === $redirect ) {
868 return;
869 }
870
871 // Filter redirect URL
872 $profile_url = bbp_get_user_profile_url( $user_id );
873 $redirect_to = apply_filters( 'bbp_check_user_edit_redirect_to', $profile_url, $user_id );
874
875 // Redirect
876 bbp_redirect( $redirect_to );
877 }
878
879 /**
880 * Check if a user is blocked, or cannot spectate the forums.
881 *
882 * @since 2.0.0 bbPress (r2996)
883 */
884 function bbp_forum_enforce_blocked() {
885
886 // Bail if not logged in or keymaster
887 if ( ! is_user_logged_in() || bbp_is_user_keymaster() ) {
888 return;
889 }
890
891 // Set 404 if in bbPress and user cannot spectate
892 if ( is_bbpress() && ! current_user_can( 'spectate' ) ) {
893 bbp_set_404();
894 }
895 }
896
897 /** Sanitization **************************************************************/
898
899 /**
900 * Sanitize displayed user data, when viewing and editing any user.
901 *
902 * This somewhat monolithic function handles the escaping and sanitization of
903 * user data for a bbPress profile. There are two reasons this all happens here:
904 *
905 * 1. bbPress took a similar approach to WordPress, and funnels all user profile
906 * data through a central helper. This eventually calls sanitize_user_field()
907 * which applies a few context based filters, which some third party plugins
908 * might be relying on bbPress to play nicely with.
909 *
910 * 2. Early versions of bbPress 2.x templates did not escape this data meaning
911 * a backwards compatible approach like this one was necessary to protect
912 * existing installations that may have custom template parts.
913 *
914 * @since 2.6.0 bbPress (r5368)
915 *
916 * @param string $value
917 * @param string $field
918 * @param string $context
919 * @return string
920 */
921 function bbp_sanitize_displayed_user_field( $value = '', $field = '', $context = 'display' ) {
922
923 // Bail if not editing or displaying (maybe we'll do more here later)
924 if ( ! in_array( $context, array( 'edit', 'display' ), true ) ) {
925 return $value;
926 }
927
928 // By default, no filter set (consider making this an array later)
929 $filter = false;
930
931 // Big switch statement to decide which user field we're sanitizing and how
932 switch ( $field ) {
933
934 // Description is a paragraph
935 case 'description' :
936 $filter = ( 'edit' === $context ) ? '' : 'wp_kses_data';
937 break;
938
939 // Email addresses are sanitized with a specific function
940 case 'user_email' :
941 $filter = 'sanitize_email';
942 break;
943
944 // Name & login fields
945 case 'user_login' :
946 case 'display_name' :
947 case 'first_name' :
948 case 'last_name' :
949 case 'nick_name' :
950 $filter = ( 'edit' === $context ) ? 'esc_attr' : 'esc_html';
951 break;
952
953 // wp-includes/default-filters.php escapes this for us via esc_url()
954 case 'user_url' :
955 break;
956 }
957
958 // Run any applicable filters on the value
959 if ( ! empty( $filter ) ) {
960 $value = call_user_func( $filter, $value );
961 }
962
963 return $value;
964 }
965
966 /** Converter *****************************************************************/
967
968 /**
969 * Convert passwords from previous platform encryption to WordPress encryption.
970 *
971 * @since 2.1.0 bbPress (r3813)
972 * @since 2.6.10 bbPress (r7244) Switched from direct query to get_user_by()
973 */
974 function bbp_user_maybe_convert_pass() {
975
976 // Sanitize login
977 $login = ! empty( $_POST['log'] )
978 ? sanitize_user( wp_unslash( $_POST['log'] ) )
979 : '';
980
981 // Sanitize password
982 $pass = ! empty( $_POST['pwd'] )
983 ? trim( $_POST['pwd'] )
984 : '';
985
986 // Bail if no username or password
987 if ( empty( $login ) || empty( $pass ) ) {
988 return;
989 }
990
991 // Get user by login...
992 $user = get_user_by( 'login', $login );
993
994 // ...or get user by email
995 if ( empty( $user ) && strpos( $login, '@' ) ) {
996 $user = get_user_by( 'email', $login );
997 }
998
999 // Bail if no user
1000 if ( empty( $user ) ) {
1001 return;
1002 }
1003
1004 // Get converter class from usermeta
1005 $class = get_user_meta( $user->ID, '_bbp_class', true );
1006
1007 // Bail if no converter class in meta
1008 if ( empty( $class ) || ! is_string( $class ) ) {
1009 return;
1010 }
1011
1012 // Setup the converter
1013 bbp_setup_converter();
1014
1015 // Try to instantiate the converter class
1016 $converter = bbp_new_converter( $class );
1017
1018 // Bail if no converter
1019 if ( empty( $converter ) ) {
1020 return;
1021 }
1022
1023 // Try to call the password conversion callback method
1024 if ( ( $converter instanceof BBP_Converter_Base ) && method_exists( $converter, 'callback_pass' ) ) {
1025 $converter->callback_pass( $login, $pass );
1026 }
1027 }
1028