PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.4.2
Forumax – AI Powered Advanced Community Forum Plugin v2.4.2
2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 trunk 1.0.8 1.1.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 2.0.0 2.1.0 All 29 releases
bbp-core / lib / bbpress / includes / users / functions.php

functions.php in Forumax – AI Powered Advanced Community Forum Plugin 2.4.2, at lib/bbpress/includes/users/functions.php

1,013 lines 28.0 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' === 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 // Nonce check
195 if ( ! bbp_verify_nonce_request( 'update-user_' . $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) editng 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( $args, array(
400 'hash' => '',
401 'newemail' => '',
402 ) );
403
404 // Bail if any relevant parameters are empty
405 if ( empty( $user_id ) || empty( $r['hash'] ) || empty( $r['newemail'] ) ) {
406 bbp_add_error( 'bbp_user_email_invalid_hash', __( '<strong>Error</strong>: An error occurred while updating your email address.', 'bbpress' ), array( 'form-field' => 'email' ) );
407 return;
408 }
409
410 // Build the nonced URL to dismiss the pending change
411 $user_login = bbp_get_displayed_user_field( 'user_login', 'raw' );
412 $user_url = bbp_get_user_profile_edit_url( $user_id );
413 $confirm_url = add_query_arg( array(
414 'action' => 'bbp-update-user-email',
415 'newuseremail' => $r['hash']
416 ), $user_url );
417
418 $email_text = __( '%1$s
419
420 Someone requested a change to the email address on your account.
421
422 Please click the following link to confirm this change:
423 %2$s
424
425 If you did not request this, you can safely ignore and delete this notification.
426
427 This email was sent to: %3$s
428
429 Regards,
430 The %4$s Team
431 %5$s', 'bbpress' );
432
433 /**
434 * Filter the email text sent when a user changes emails.
435 *
436 * The following strings have a special meaning and will get replaced dynamically:
437 *
438 * %1$s - The current user's username
439 * %2$s - The link to click on to confirm the email change
440 * %3$s - The new email
441 * %4$s - The name of the site
442 * %5$s - The URL to the site
443 *
444 * @param string $email_text Text in the email.
445 * @param string $r New user email that the current user has changed to.
446 */
447 $content = apply_filters( 'bbp_user_email_update_content', $email_text, $r );
448
449 // Build the email message
450 $message = sprintf( $content, $user_login, $confirm_url, $r['newemail'], get_site_option( 'site_name' ), network_home_url() );
451
452 // Build the email subject
453 $subject = sprintf( __( '[%s] New Email Address', 'bbpress' ), wp_specialchars_decode( get_option( 'blogname' ) ) );
454
455 // Send the email
456 wp_mail( $r['newemail'], $subject, $message );
457 }
458
459 /**
460 * Conditionally hook the core WordPress output actions to the end of the
461 * default user's edit profile template
462 *
463 * This allows clever plugin authors to conditionally unhook the WordPress core
464 * output actions if they don't want any unexpected junk to appear there, and
465 * also avoids needing to pollute the templates with additional logic and actions.
466 *
467 * @since 2.2.0 bbPress (r4273)
468 */
469 function bbp_user_edit_after() {
470 $action = bbp_is_user_home_edit() ? 'show_user_profile' : 'edit_user_profile';
471
472 do_action( $action, get_userdata( bbp_get_displayed_user_id() ) );
473 }
474
475 /** User Queries **************************************************************/
476
477 /**
478 * Get the topics that a user created
479 *
480 * @since 2.0.0 bbPress (r2660)
481 * @since 2.6.0 bbPress (r6618) Signature changed to accept an array of arguments
482 *
483 * @param array $args Optional. Arguments to pass into bbp_has_topics()
484 *
485 * @return bool True if user has started topics, otherwise false
486 */
487 function bbp_get_user_topics_started( $args = array() ) {
488
489 // Backwards compat for pre-2.6.0
490 if ( is_numeric( $args ) ) {
491 $args = array(
492 'author' => bbp_get_user_id( $args, false, false )
493 );
494 }
495
496 // Default arguments
497 $defaults = array(
498 'author' => bbp_get_displayed_user_id()
499 );
500
501 // Parse arguments
502 $r = bbp_parse_args( $args, $defaults, 'get_user_topics_started' );
503
504 // Get the topics
505 $query = bbp_has_topics( $r );
506 $user_id = $r['author'];
507
508 // Filter & return
509 return apply_filters( 'bbp_get_user_topics_started', $query, $user_id, $r, $args );
510 }
511
512 /**
513 * Get the replies that a user created
514 *
515 * @since 2.2.0 bbPress (r4225)
516 * @since 2.6.0 bbPress (r6618) Signature changed to accept an array of arguments
517 *
518 * @param array $args Optional. Arguments to pass into bbp_has_replies()
519 *
520 * @return bool True if user has created replies, otherwise false
521 */
522 function bbp_get_user_replies_created( $args = array() ) {
523
524 // Backwards compat for pre-2.6.0
525 if ( is_numeric( $args ) ) {
526 $args = array(
527 'author' => bbp_get_user_id( $args, false, false ),
528 'post_type' => bbp_get_reply_post_type(),
529 'order' => 'DESC'
530 );
531 }
532
533 // Default arguments
534 $defaults = array(
535 'author' => bbp_get_displayed_user_id(),
536 'post_type' => bbp_get_reply_post_type(),
537 'order' => 'DESC'
538 );
539
540 // Parse arguments
541 $r = bbp_parse_args( $args, $defaults, 'get_user_replies_created' );
542
543 // Get the replies
544 $query = bbp_has_replies( $r );
545 $user_id = $r['author'];
546
547 // Filter & return
548 return apply_filters( 'bbp_get_user_replies_created', $query, $user_id, $r, $args );
549 }
550
551 /**
552 * Get user IDs from nicenames
553 *
554 * This function is primarily used when saving object moderators
555 *
556 * @since 2.6.0 bbPress
557 *
558 * @param mixed $user_nicenames
559 * @return array
560 */
561 function bbp_get_user_ids_from_nicenames( $user_nicenames = array() ) {
562
563 // Default value
564 $retval = array();
565
566 // Only query if nicenames
567 if ( ! empty( $user_nicenames ) ) {
568
569 // Maybe explode by comma
570 $user_nicenames = ( is_string( $user_nicenames ) && strstr( $user_nicenames, ',' ) )
571 ? explode( ',', $user_nicenames )
572 : (array) $user_nicenames;
573
574 // Sanitize each nicename in the array
575 $user_nicenames = array_map( 'sanitize_title', $user_nicenames );
576
577 // Get users
578 $users = get_users( array(
579 'nicename__in' => $user_nicenames
580 ) );
581
582 // Pluck or empty
583 if ( ! empty( $users ) ) {
584 $retval = wp_list_pluck( $users, 'ID' );
585 }
586 }
587
588 // Filter & return
589 return (array) apply_filters( 'bbp_get_user_ids_from_nicenames', $retval, $user_nicenames );
590 }
591
592 /**
593 * Get user nicenames from IDs
594 *
595 * This function is primarily used when saving object moderators
596 *
597 * @since 2.6.0 bbPress
598 *
599 * @param mixed $user_ids
600 * @return array
601 */
602 function bbp_get_user_nicenames_from_ids( $user_ids = array() ) {
603
604 // Default value
605 $retval = array();
606
607 // Only query if nicenames
608 if ( ! empty( $user_ids ) ) {
609
610 // Get users
611 $users = get_users( array(
612 'include' => $user_ids
613 ) );
614
615 // Pluck or empty
616 if ( ! empty( $users ) ) {
617 $retval = wp_list_pluck( $users, 'user_nicename' );
618 }
619 }
620
621 // Filter & return
622 return (array) apply_filters( 'bbp_get_user_nicenames_from_ids', $retval, $user_ids );
623 }
624
625 /** Post Counts ***************************************************************/
626
627 /**
628 * Return the raw database count of topics by a user
629 *
630 * @since 2.1.0 bbPress (r3633)
631 *
632 * @param int $user_id User ID to get count for
633 *
634 * @return int Raw DB count of topics
635 */
636 function bbp_get_user_topic_count_raw( $user_id = 0 ) {
637 $user_id = bbp_get_user_id( $user_id );
638 $bbp_db = bbp_db();
639 $statii = "'" . implode( "', '", bbp_get_public_topic_statuses() ) . "'";
640 $sql = "SELECT COUNT(*)
641 FROM {$bbp_db->posts}
642 WHERE post_author = %d
643 AND post_type = %s
644 AND post_status IN ({$statii})";
645
646 $query = $bbp_db->prepare( $sql, $user_id, bbp_get_topic_post_type() );
647 $count = (int) $bbp_db->get_var( $query );
648
649 // Filter & return
650 return (int) apply_filters( 'bbp_get_user_topic_count_raw', $count, $user_id );
651 }
652
653 /**
654 * Return the raw database count of replies by a user
655 *
656 * @since 2.1.0 bbPress (r3633)
657 *
658 * @param int $user_id User ID to get count for
659 *
660 * @return int Raw DB count of replies
661 */
662 function bbp_get_user_reply_count_raw( $user_id = 0 ) {
663 $user_id = bbp_get_user_id( $user_id );
664 $bbp_db = bbp_db();
665 $statii = "'" . implode( "', '", bbp_get_public_reply_statuses() ) . "'";
666 $sql = "SELECT COUNT(*)
667 FROM {$bbp_db->posts}
668 WHERE post_author = %d
669 AND post_type = %s
670 AND post_status IN ({$statii})";
671
672 $query = $bbp_db->prepare( $sql, $user_id, bbp_get_reply_post_type() );
673 $count = (int) $bbp_db->get_var( $query );
674
675 // Filter & return
676 return (int) apply_filters( 'bbp_get_user_reply_count_raw', $count, $user_id );
677 }
678
679 /**
680 * Bump the topic count for a user by a certain amount.
681 *
682 * @since 2.6.0 bbPress (r5309)
683 *
684 * @param int $user_id
685 * @param int $difference
686 */
687 function bbp_bump_user_topic_count( $user_id = 0, $difference = 1 ) {
688
689 // Bail if no bump
690 if ( empty( $difference ) ) {
691 return false;
692 }
693
694 // Validate user ID
695 $user_id = bbp_get_user_id( $user_id );
696 if ( empty( $user_id ) ) {
697 return false;
698 }
699
700 // Check meta for count, or query directly if not found
701 $count = bbp_get_user_topic_count( $user_id, true );
702 if ( empty( $count ) ) {
703 $count = bbp_get_user_topic_count_raw( $user_id );
704 }
705
706 $difference = (int) $difference;
707 $user_topic_count = (int) ( $count + $difference );
708
709 // Add them up and filter them
710 $new_count = (int) apply_filters( 'bbp_bump_user_topic_count', $user_topic_count, $user_id, $difference, $count );
711
712 return bbp_update_user_topic_count( $user_id, $new_count );
713 }
714
715 /**
716 * Bump the reply count for a user by a certain amount.
717 *
718 * @since 2.6.0 bbPress (r5309)
719 *
720 * @param int $user_id
721 * @param int $difference
722 */
723 function bbp_bump_user_reply_count( $user_id = 0, $difference = 1 ) {
724
725 // Bail if no bump
726 if ( empty( $difference ) ) {
727 return false;
728 }
729
730 // Validate user ID
731 $user_id = bbp_get_user_id( $user_id );
732 if ( empty( $user_id ) ) {
733 return false;
734 }
735
736 // Check meta for count, or query directly if not found
737 $count = bbp_get_user_reply_count( $user_id, true );
738 if ( empty( $count ) ) {
739 $count = bbp_get_user_reply_count_raw( $user_id );
740 }
741
742 $difference = (int) $difference;
743 $user_reply_count = (int) ( $count + $difference );
744
745 // Add them up and filter them
746 $new_count = (int) apply_filters( 'bbp_bump_user_reply_count', $user_reply_count, $user_id, $difference, $count );
747
748 return bbp_update_user_reply_count( $user_id, $new_count );
749 }
750
751 /**
752 * Helper function used to increase (by one) the count of topics for a user when
753 * a topic is published.
754 *
755 * @since 2.6.0 bbPress (r5309)
756 *
757 * @access
758 * @param $topic_id
759 * @param $forum_id
760 * @param $anonymous_data
761 * @param $topic_author
762 */
763 function bbp_increase_user_topic_count( $topic_id = 0 ) {
764 $user_id = bbp_get_topic_author_id( $topic_id );
765 return bbp_bump_user_topic_count( $user_id, 1 );
766 }
767
768 /**
769 * Helper function used to increase (by one) the count of replies for a user when
770 * a reply is published.
771 *
772 * This is a helper function, hooked to `bbp_new_reply`
773 *
774 * @since 2.6.0 bbPress (r5309)
775 *
776 * @param $topic_id
777 * @param $forum_id
778 * @param $anonymous_data
779 * @param $topic_author
780 */
781 function bbp_increase_user_reply_count( $reply_id = 0 ) {
782 $user_id = bbp_get_reply_author_id( $reply_id );
783 return bbp_bump_user_reply_count( $user_id, 1 );
784 }
785
786 /**
787 * Helper function used to decrease (by one) the count of topics for a user when
788 * a topic is unpublished.
789 *
790 * @since 2.6.0 bbPress (r5309)
791 *
792 * @param $topic_id
793 */
794 function bbp_decrease_user_topic_count( $topic_id = 0 ) {
795 $user_id = bbp_get_topic_author_id( $topic_id );
796 return bbp_bump_user_topic_count( $user_id, -1 );
797 }
798
799 /**
800 * Helper function used to increase (by one) the count of replies for a user when
801 * a topic is unpublished.
802 *
803 * @since 2.6.0 bbPress (r5309)
804 *
805 * @param $reply_id
806 */
807 function bbp_decrease_user_reply_count( $reply_id = 0 ) {
808 $user_id = bbp_get_reply_author_id( $reply_id );
809 return bbp_bump_user_reply_count( $user_id, -1 );
810 }
811
812 /** Permissions ***************************************************************/
813
814 /**
815 * Redirect if unauthorized user is attempting to edit another user
816 *
817 * This is hooked to 'bbp_template_redirect' and controls the conditions under
818 * which a user can edit another user (or themselves.) If these conditions are
819 * met, we assume a user cannot perform this task, and look for ways they can
820 * earn the ability to access this template.
821 *
822 * @since 2.1.0 bbPress (r3605)
823 */
824 function bbp_check_user_edit() {
825
826 // Bail if not editing a user
827 if ( ! bbp_is_single_user_edit() ) {
828 return;
829 }
830
831 // Default to false
832 $redirect = true;
833 $user_id = bbp_get_displayed_user_id();
834
835 // Allow user to edit their own profile
836 if ( bbp_is_user_home_edit() ) {
837 $redirect = false;
838
839 // Allow if current user can edit the displayed user
840 } elseif ( current_user_can( 'edit_user', $user_id ) ) {
841 $redirect = false;
842
843 // Allow if user can manage network users, or edit-any is enabled
844 } elseif ( current_user_can( 'manage_network_users' ) || apply_filters( 'enable_edit_any_user_configuration', false ) ) {
845 $redirect = false;
846 }
847
848 // Allow conclusion to be overridden
849 $redirect = (bool) apply_filters( 'bbp_check_user_edit', $redirect, $user_id );
850
851 // Bail if not redirecting
852 if ( false === $redirect ) {
853 return;
854 }
855
856 // Filter redirect URL
857 $profile_url = bbp_get_user_profile_url( $user_id );
858 $redirect_to = apply_filters( 'bbp_check_user_edit_redirect_to', $profile_url, $user_id );
859
860 // Redirect
861 bbp_redirect( $redirect_to );
862 }
863
864 /**
865 * Check if a user is blocked, or cannot spectate the forums.
866 *
867 * @since 2.0.0 bbPress (r2996)
868 */
869 function bbp_forum_enforce_blocked() {
870
871 // Bail if not logged in or keymaster
872 if ( ! is_user_logged_in() || bbp_is_user_keymaster() ) {
873 return;
874 }
875
876 // Set 404 if in bbPress and user cannot spectate
877 if ( is_bbpress() && ! current_user_can( 'spectate' ) ) {
878 bbp_set_404();
879 }
880 }
881
882 /** Sanitization **************************************************************/
883
884 /**
885 * Sanitize displayed user data, when viewing and editing any user.
886 *
887 * This somewhat monolithic function handles the escaping and sanitization of
888 * user data for a bbPress profile. There are two reasons this all happens here:
889 *
890 * 1. bbPress took a similar approach to WordPress, and funnels all user profile
891 * data through a central helper. This eventually calls sanitize_user_field()
892 * which applies a few context based filters, which some third party plugins
893 * might be relying on bbPress to play nicely with.
894 *
895 * 2. Early versions of bbPress 2.x templates did not escape this data meaning
896 * a backwards compatible approach like this one was necessary to protect
897 * existing installations that may have custom template parts.
898 *
899 * @since 2.6.0 bbPress (r5368)
900 *
901 * @param string $value
902 * @param string $field
903 * @param string $context
904 * @return string
905 */
906 function bbp_sanitize_displayed_user_field( $value = '', $field = '', $context = 'display' ) {
907
908 // Bail if not editing or displaying (maybe we'll do more here later)
909 if ( ! in_array( $context, array( 'edit', 'display' ), true ) ) {
910 return $value;
911 }
912
913 // By default, no filter set (consider making this an array later)
914 $filter = false;
915
916 // Big switch statement to decide which user field we're sanitizing and how
917 switch ( $field ) {
918
919 // Description is a paragraph
920 case 'description' :
921 $filter = ( 'edit' === $context ) ? '' : 'wp_kses_data';
922 break;
923
924 // Email addresses are sanitized with a specific function
925 case 'user_email' :
926 $filter = 'sanitize_email';
927 break;
928
929 // Name & login fields
930 case 'user_login' :
931 case 'display_name' :
932 case 'first_name' :
933 case 'last_name' :
934 case 'nick_name' :
935 $filter = ( 'edit' === $context ) ? 'esc_attr' : 'esc_html';
936 break;
937
938 // wp-includes/default-filters.php escapes this for us via esc_url()
939 case 'user_url' :
940 break;
941 }
942
943 // Run any applicable filters on the value
944 if ( ! empty( $filter ) ) {
945 $value = call_user_func( $filter, $value );
946 }
947
948 return $value;
949 }
950
951 /** Converter *****************************************************************/
952
953 /**
954 * Convert passwords from previous platform encryption to WordPress encryption.
955 *
956 * @since 2.1.0 bbPress (r3813)
957 * @since 2.6.10 bbPress (r7244) Switched from direct query to get_user_by()
958 */
959 function bbp_user_maybe_convert_pass() {
960
961 // Sanitize login
962 $login = ! empty( $_POST['log'] )
963 ? sanitize_user( wp_unslash( $_POST['log'] ) )
964 : '';
965
966 // Sanitize password
967 $pass = ! empty( $_POST['pwd'] )
968 ? trim( $_POST['pwd'] )
969 : '';
970
971 // Bail if no username or password
972 if ( empty( $login ) || empty( $pass ) ) {
973 return;
974 }
975
976 // Get user by login...
977 $user = get_user_by( 'login', $login );
978
979 // ...or get user by email
980 if ( empty( $user ) && strpos( $login, '@' ) ) {
981 $user = get_user_by( 'email', $login );
982 }
983
984 // Bail if no user
985 if ( empty( $user ) ) {
986 return;
987 }
988
989 // Get converter class from usermeta
990 $class = get_user_meta( $user->ID, '_bbp_class', true );
991
992 // Bail if no converter class in meta
993 if ( empty( $class ) || ! is_string( $class ) ) {
994 return;
995 }
996
997 // Setup the converter
998 bbp_setup_converter();
999
1000 // Try to instantiate the converter class
1001 $converter = bbp_new_converter( $class );
1002
1003 // Bail if no converter
1004 if ( empty( $converter ) ) {
1005 return;
1006 }
1007
1008 // Try to call the password conversion callback method
1009 if ( ( $converter instanceof BBP_Converter_Base ) && method_exists( $converter, 'callback_pass' ) ) {
1010 $converter->callback_pass( $login, $pass );
1011 }
1012 }
1013