/** * bbPress User Functions * * @package bbPress * @subpackage Functions */ // Exit if accessed directly defined( 'ABSPATH' ) || exit; /** * Redirect back to $url when attempting to use the login page * * @since 2.0.0 bbPress (r2815) * * @param string $url The url * @param string $raw_url Raw url * @param object $user User object */ function bbp_redirect_login( $url = '', $raw_url = '', $user = '' ) { // Raw redirect_to was passed, so use it if ( ! empty( $raw_url ) ) { $url = $raw_url; // $url was manually set in wp-login.php to redirect to admin } elseif ( admin_url() === $url ) { $url = home_url(); // $url is empty } elseif ( empty( $url ) ) { $url = home_url(); } // Filter & return return apply_filters( 'bbp_redirect_login', $url, $raw_url, $user ); } /** * Is an anonymous topic/reply being made? * * @since 2.0.0 bbPress (r2688) * * @return bool True if anonymous is allowed and user is not logged in, false if * anonymous is not allowed or user is logged in */ function bbp_is_anonymous() { $is_anonymous = ( ! is_user_logged_in() && bbp_allow_anonymous() ); // Filter & return return (bool) apply_filters( 'bbp_is_anonymous', $is_anonymous ); } /** * Echoes the values for current poster (uses WP comment cookies) * * @since 2.0.0 bbPress (r2734) * * @param string $key Which value to echo? */ function bbp_current_anonymous_user_data( $key = '' ) { echo esc_attr( bbp_get_current_anonymous_user_data( $key ) ); } /** * Get the cookies for current poster (uses WP comment cookies). * * @since 2.0.0 bbPress (r2734) * * @param string $key Optional. Which value to get? If not given, then * an array is returned. * @return string|array Cookie(s) for current poster */ function bbp_get_current_anonymous_user_data( $key = '' ) { // Array of allowed cookie names $cookie_names = array( 'name' => 'comment_author', 'email' => 'comment_author_email', 'url' => 'comment_author_url', // Here just for the sake of them, use the above ones 'comment_author' => 'comment_author', 'comment_author_email' => 'comment_author_email', 'comment_author_url' => 'comment_author_url', ); // Get the current poster's info from the cookies $bbp_current_poster = wp_get_current_commenter(); // Sanitize the cookie key being retrieved $key = sanitize_key( $key ); // Maybe return a specific key if ( ! empty( $key ) && in_array( $key, array_keys( $cookie_names ), true ) ) { return $bbp_current_poster[ $cookie_names[ $key ] ]; } // Return all keys return $bbp_current_poster; } /** * Set the cookies for current poster (uses WP comment cookies) * * @since 2.0.0 bbPress (r2734) * * @param array $anonymous_data Optional - if it's an anonymous post. Do not * supply if supplying $author_id. Should be * sanitized (see {@link bbp_filter_anonymous_post_data()} */ function bbp_set_current_anonymous_user_data( $anonymous_data = array() ) { // Bail if empty or not an array if ( empty( $anonymous_data ) || ! is_array( $anonymous_data ) ) { return; } // Setup cookie expiration $lifetime = (int) apply_filters( 'comment_cookie_lifetime', 30000000 ); $expiry = time() + $lifetime; $secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ); // Set the cookies setcookie( 'comment_author_' . COOKIEHASH, $anonymous_data['bbp_anonymous_name'], $expiry, COOKIEPATH, COOKIE_DOMAIN, $secure ); setcookie( 'comment_author_email_' . COOKIEHASH, $anonymous_data['bbp_anonymous_email'], $expiry, COOKIEPATH, COOKIE_DOMAIN, $secure ); setcookie( 'comment_author_url_' . COOKIEHASH, $anonymous_data['bbp_anonymous_website'], $expiry, COOKIEPATH, COOKIE_DOMAIN, $secure ); } /** * Get the poster IP address * * @since 2.0.0 bbPress (r3120) * @since 2.6.0 bbPress (r5609) Added `empty()` check for unit tests * * @return string */ function bbp_current_author_ip() { // Check for remote address $remote_address = ! empty( $_SERVER['REMOTE_ADDR'] ) ? wp_unslash( $_SERVER['REMOTE_ADDR'] ) : '127.0.0.1'; // Remove any unsavory bits $retval = preg_replace( '/[^0-9a-fA-F:., ]/', '', $remote_address ); // Filter & return return apply_filters( 'bbp_current_author_ip', $retval, $remote_address ); } /** * Get the poster user agent * * @since 2.0.0 bbPress (r3446) * * @return string */ function bbp_current_author_ua() { $retval = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? mb_substr( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ), 0, 254 ) : ''; // Filter & return return apply_filters( 'bbp_current_author_ua', $retval ); } /** Edit **********************************************************************/ /** * Handles the front end user editing from POST requests * * @since 2.0.0 bbPress (r2790) * * @param string $action The requested action to compare this function to */ function bbp_edit_user_handler( $action = '' ) { // Bail if action is not `bbp-update-user` if ( 'bbp-update-user' !== $action ) { return; } // Bail if in wp-admin if ( is_admin() ) { return; } // Get the displayed user ID $user_id = bbp_get_displayed_user_id(); // Nonce check if ( ! bbp_verify_nonce_request( 'update-user_' . $user_id ) ) { bbp_add_error( 'bbp_update_user_nonce', __( 'Error: Are you sure you wanted to do that?', 'bbpress' ) ); return; } // Cap check if ( ! current_user_can( 'edit_user', $user_id ) ) { bbp_add_error( 'bbp_update_user_capability', __( 'Error: Are you sure you wanted to do that?', 'bbpress' ) ); return; } // Empty email check if ( empty( $_POST['email'] ) ) { bbp_add_error( 'bbp_user_email_empty', __( 'Error: That is not a valid email address.', 'bbpress' ), array( 'form-field' => 'email' ) ); return; } // Get the users current email address to use for comparisons $user_email = bbp_get_displayed_user_field( 'user_email', 'raw' ); // Bail if no email change if ( $user_email !== $_POST['email'] ) { // Check that new email address is valid if ( ! is_email( $_POST['email'] ) ) { bbp_add_error( 'bbp_user_email_invalid', __( 'Error: That is not a valid email address.', 'bbpress' ), array( 'form-field' => 'email' ) ); return; } // Check if email address is already in use if ( email_exists( $_POST['email'] ) ) { bbp_add_error( 'bbp_user_email_taken', __( 'Error: That email address is already in use.', 'bbpress' ), array( 'form-field' => 'email' ) ); return; } // Update the option $option = array( 'hash' => md5( $_POST['email'] . time() . wp_rand() ), 'newemail' => $_POST['email'], ); update_user_meta( $user_id, '_new_email', $option ); // Attempt to notify the user of email address change bbp_edit_user_email_send_notification( $user_id, $option ); // Set the POST email variable back to the user's email address // so `edit_user()` does not attempt to update it. This is not ideal, // but it's also what send_confirmation_on_profile_email() does. $_POST['email'] = $user_email; } // Do action based on who's profile you're editing $edit_action = bbp_is_user_home_edit() ? 'personal_options_update' : 'edit_user_profile_update'; do_action( $edit_action, $user_id ); // Prevent edit_user() from wiping out the user's Toolbar on front setting if ( ! isset( $_POST['admin_bar_front'] ) && _get_admin_bar_pref( 'front', $user_id ) ) { $_POST['admin_bar_front'] = 1; } // Bail if errors already exist if ( bbp_has_errors() ) { return; } // Handle user edit $edit_user = edit_user( $user_id ); // Error(s) editng the user, so copy them into the global if ( is_wp_error( $edit_user ) ) { bbpress()->errors = $edit_user; // Successful edit to redirect } elseif ( is_integer( $edit_user ) ) { // Maybe update super admin ability if ( is_multisite() && ! bbp_is_user_home_edit() && current_user_can( 'manage_network_options' ) && is_super_admin() ) { empty( $_POST['super_admin'] ) ? revoke_super_admin( $edit_user ) : grant_super_admin( $edit_user ); } // Redirect $args = array( 'updated' => 'true' ); $user_url = bbp_get_user_profile_edit_url( $edit_user ); $redirect = add_query_arg( $args, $user_url ); bbp_redirect( $redirect ); } } /** * Handles user email address updating from GET requests * * @since 2.6.0 bbPress (r5660) * * @param string $action */ function bbp_user_email_change_handler( $action = '' ) { // Bail if action is not `bbp-update-user-email` if ( 'bbp-update-user-email' !== $action ) { return; } // Bail if not on users own profile if ( ! bbp_is_user_home_edit() ) { return; } // Bail if not attempting to modify user email address if ( empty( $_GET['newuseremail'] ) && empty( $_GET['dismiss'] ) ) { return; } // Get the displayed user ID & option key $user_id = bbp_get_displayed_user_id(); $key = '_new_email'; $redirect_to = bbp_get_user_profile_edit_url( $user_id ); // Execute confirmed email change. if ( ! empty( $_GET['newuseremail'] ) ) { // Check for email address change option $new_email = get_user_meta( $user_id, $key, true ); // Redirect if *no* email address change exists if ( false === $new_email ) { bbp_redirect( $redirect_to ); } // Cleanup & redirect if *invalid* email address change exists if ( empty( $new_email['hash'] ) || empty( $new_email['newemail'] ) ) { delete_user_meta( $user_id, $key ); bbp_redirect( $redirect_to ); } // Compare hashes, and update user if hashes match if ( hash_equals( $new_email['hash'], $_GET['newuseremail'] ) ) { // Does another user have this email address already? if ( email_exists( $new_email['newemail'] ) ) { delete_user_meta( $user_id, $key ); bbp_add_error( 'bbp_user_email_taken', __( 'Error: That email address is already in use.', 'bbpress' ), array( 'form-field' => 'email' ) ); // Email address is good to change to } else { // Create a stdClass (for easy call to wp_update_user()) $user = new stdClass(); $user->ID = $user_id; $user->user_email = esc_html( trim( $new_email['newemail'] ) ); // Attempt to update user email $update_user = wp_update_user( $user ); // Error(s) editing the user, so copy them into the global if ( is_wp_error( $update_user ) ) { bbpress()->errors = $update_user; // All done, so redirect and show the updated message } else { // Update signups table, if signups table & entry exists // For Multisite & BuddyPress compatibility $bbp_db = bbp_db(); 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' ) ) ) ) { $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' ) ) ); } delete_user_meta( $user_id, $key ); bbp_redirect( add_query_arg( array( 'updated' => 'true' ), $redirect_to ) ); } } } // Delete new email address from user options } elseif ( ! empty( $_GET['dismiss'] ) && ( "{$user_id}{$key}" === $_GET['dismiss'] ) ) { if ( ! bbp_verify_nonce_request( "dismiss-{$user_id}{$key}" ) ) { bbp_add_error( 'bbp_dismiss_new_email_nonce', __( 'Error: Are you sure you wanted to do that?', 'bbpress' ) ); return; } delete_user_meta( $user_id, $key ); bbp_redirect( $redirect_to ); } } /** * Sends an email when an email address change occurs on POST requests * * @since 2.6.0 bbPress (r5660) * * @see send_confirmation_on_profile_email() */ function bbp_edit_user_email_send_notification( $user_id = 0, $args = array() ) { // Parse args $r = bbp_parse_args( $args, array( 'hash' => '', 'newemail' => '', ) ); // Bail if any relevant parameters are empty if ( empty( $user_id ) || empty( $r['hash'] ) || empty( $r['newemail'] ) ) { bbp_add_error( 'bbp_user_email_invalid_hash', __( 'Error: An error occurred while updating your email address.', 'bbpress' ), array( 'form-field' => 'email' ) ); return; } // Build the nonced URL to dismiss the pending change $user_login = bbp_get_displayed_user_field( 'user_login', 'raw' ); $user_url = bbp_get_user_profile_edit_url( $user_id ); $confirm_url = add_query_arg( array( 'action' => 'bbp-update-user-email', 'newuseremail' => $r['hash'] ), $user_url ); $email_text = __( '%1$s Someone requested a change to the email address on your account. Please click the following link to confirm this change: %2$s If you did not request this, you can safely ignore and delete this notification. This email was sent to: %3$s Regards, The %4$s Team %5$s', 'bbpress' ); /** * Filter the email text sent when a user changes emails. * * The following strings have a special meaning and will get replaced dynamically: * * %1$s - The current user's username * %2$s - The link to click on to confirm the email change * %3$s - The new email * %4$s - The name of the site * %5$s - The URL to the site * * @param string $email_text Text in the email. * @param string $r New user email that the current user has changed to. */ $content = apply_filters( 'bbp_user_email_update_content', $email_text, $r ); // Build the email message $message = sprintf( $content, $user_login, $confirm_url, $r['newemail'], get_site_option( 'site_name' ), network_home_url() ); // Build the email subject $subject = sprintf( __( '[%s] New Email Address', 'bbpress' ), wp_specialchars_decode( get_option( 'blogname' ) ) ); // Send the email wp_mail( $r['newemail'], $subject, $message ); } /** * Conditionally hook the core WordPress output actions to the end of the * default user's edit profile template * * This allows clever plugin authors to conditionally unhook the WordPress core * output actions if they don't want any unexpected junk to appear there, and * also avoids needing to pollute the templates with additional logic and actions. * * @since 2.2.0 bbPress (r4273) */ function bbp_user_edit_after() { $action = bbp_is_user_home_edit() ? 'show_user_profile' : 'edit_user_profile'; do_action( $action, get_userdata( bbp_get_displayed_user_id() ) ); } /** User Queries **************************************************************/ /** * Get the topics that a user created * * @since 2.0.0 bbPress (r2660) * @since 2.6.0 bbPress (r6618) Signature changed to accept an array of arguments * * @param array $args Optional. Arguments to pass into bbp_has_topics() * * @return bool True if user has started topics, otherwise false */ function bbp_get_user_topics_started( $args = array() ) { // Backwards compat for pre-2.6.0 if ( is_numeric( $args ) ) { $args = array( 'author' => bbp_get_user_id( $args, false, false ) ); } // Default arguments $defaults = array( 'author' => bbp_get_displayed_user_id() ); // Parse arguments $r = bbp_parse_args( $args, $defaults, 'get_user_topics_started' ); // Get the topics $query = bbp_has_topics( $r ); $user_id = $r['author']; // Filter & return return apply_filters( 'bbp_get_user_topics_started', $query, $user_id, $r, $args ); } /** * Get the replies that a user created * * @since 2.2.0 bbPress (r4225) * @since 2.6.0 bbPress (r6618) Signature changed to accept an array of arguments * * @param array $args Optional. Arguments to pass into bbp_has_replies() * * @return bool True if user has created replies, otherwise false */ function bbp_get_user_replies_created( $args = array() ) { // Backwards compat for pre-2.6.0 if ( is_numeric( $args ) ) { $args = array( 'author' => bbp_get_user_id( $args, false, false ), 'post_type' => bbp_get_reply_post_type(), 'order' => 'DESC' ); } // Default arguments $defaults = array( 'author' => bbp_get_displayed_user_id(), 'post_type' => bbp_get_reply_post_type(), 'order' => 'DESC' ); // Parse arguments $r = bbp_parse_args( $args, $defaults, 'get_user_replies_created' ); // Get the replies $query = bbp_has_replies( $r ); $user_id = $r['author']; // Filter & return return apply_filters( 'bbp_get_user_replies_created', $query, $user_id, $r, $args ); } /** * Get user IDs from nicenames * * This function is primarily used when saving object moderators * * @since 2.6.0 bbPress * * @param mixed $user_nicenames * @return array */ function bbp_get_user_ids_from_nicenames( $user_nicenames = array() ) { // Default value $retval = array(); // Only query if nicenames if ( ! empty( $user_nicenames ) ) { // Maybe explode by comma $user_nicenames = ( is_string( $user_nicenames ) && strstr( $user_nicenames, ',' ) ) ? explode( ',', $user_nicenames ) : (array) $user_nicenames; // Sanitize each nicename in the array $user_nicenames = array_map( 'sanitize_title', $user_nicenames ); // Get users $users = get_users( array( 'nicename__in' => $user_nicenames ) ); // Pluck or empty if ( ! empty( $users ) ) { $retval = wp_list_pluck( $users, 'ID' ); } } // Filter & return return (array) apply_filters( 'bbp_get_user_ids_from_nicenames', $retval, $user_nicenames ); } /** * Get user nicenames from IDs * * This function is primarily used when saving object moderators * * @since 2.6.0 bbPress * * @param mixed $user_ids * @return array */ function bbp_get_user_nicenames_from_ids( $user_ids = array() ) { // Default value $retval = array(); // Only query if nicenames if ( ! empty( $user_ids ) ) { // Get users $users = get_users( array( 'include' => $user_ids ) ); // Pluck or empty if ( ! empty( $users ) ) { $retval = wp_list_pluck( $users, 'user_nicename' ); } } // Filter & return return (array) apply_filters( 'bbp_get_user_nicenames_from_ids', $retval, $user_ids ); } /** Post Counts ***************************************************************/ /** * Return the raw database count of topics by a user * * @since 2.1.0 bbPress (r3633) * * @param int $user_id User ID to get count for * * @return int Raw DB count of topics */ function bbp_get_user_topic_count_raw( $user_id = 0 ) { $user_id = bbp_get_user_id( $user_id ); $bbp_db = bbp_db(); $statii = "'" . implode( "', '", bbp_get_public_topic_statuses() ) . "'"; $sql = "SELECT COUNT(*) FROM {$bbp_db->posts} WHERE post_author = %d AND post_type = %s AND post_status IN ({$statii})"; $query = $bbp_db->prepare( $sql, $user_id, bbp_get_topic_post_type() ); $count = (int) $bbp_db->get_var( $query ); // Filter & return return (int) apply_filters( 'bbp_get_user_topic_count_raw', $count, $user_id ); } /** * Return the raw database count of replies by a user * * @since 2.1.0 bbPress (r3633) * * @param int $user_id User ID to get count for * * @return int Raw DB count of replies */ function bbp_get_user_reply_count_raw( $user_id = 0 ) { $user_id = bbp_get_user_id( $user_id ); $bbp_db = bbp_db(); $statii = "'" . implode( "', '", bbp_get_public_reply_statuses() ) . "'"; $sql = "SELECT COUNT(*) FROM {$bbp_db->posts} WHERE post_author = %d AND post_type = %s AND post_status IN ({$statii})"; $query = $bbp_db->prepare( $sql, $user_id, bbp_get_reply_post_type() ); $count = (int) $bbp_db->get_var( $query ); // Filter & return return (int) apply_filters( 'bbp_get_user_reply_count_raw', $count, $user_id ); } /** * Bump the topic count for a user by a certain amount. * * @since 2.6.0 bbPress (r5309) * * @param int $user_id * @param int $difference */ function bbp_bump_user_topic_count( $user_id = 0, $difference = 1 ) { // Bail if no bump if ( empty( $difference ) ) { return false; } // Validate user ID $user_id = bbp_get_user_id( $user_id ); if ( empty( $user_id ) ) { return false; } // Check meta for count, or query directly if not found $count = bbp_get_user_topic_count( $user_id, true ); if ( empty( $count ) ) { $count = bbp_get_user_topic_count_raw( $user_id ); } $difference = (int) $difference; $user_topic_count = (int) ( $count + $difference ); // Add them up and filter them $new_count = (int) apply_filters( 'bbp_bump_user_topic_count', $user_topic_count, $user_id, $difference, $count ); return bbp_update_user_topic_count( $user_id, $new_count ); } /** * Bump the reply count for a user by a certain amount. * * @since 2.6.0 bbPress (r5309) * * @param int $user_id * @param int $difference */ function bbp_bump_user_reply_count( $user_id = 0, $difference = 1 ) { // Bail if no bump if ( empty( $difference ) ) { return false; } // Validate user ID $user_id = bbp_get_user_id( $user_id ); if ( empty( $user_id ) ) { return false; } // Check meta for count, or query directly if not found $count = bbp_get_user_reply_count( $user_id, true ); if ( empty( $count ) ) { $count = bbp_get_user_reply_count_raw( $user_id ); } $difference = (int) $difference; $user_reply_count = (int) ( $count + $difference ); // Add them up and filter them $new_count = (int) apply_filters( 'bbp_bump_user_reply_count', $user_reply_count, $user_id, $difference, $count ); return bbp_update_user_reply_count( $user_id, $new_count ); } /** * Helper function used to increase (by one) the count of topics for a user when * a topic is published. * * @since 2.6.0 bbPress (r5309) * * @access * @param $topic_id * @param $forum_id * @param $anonymous_data * @param $topic_author */ function bbp_increase_user_topic_count( $topic_id = 0 ) { $user_id = bbp_get_topic_author_id( $topic_id ); return bbp_bump_user_topic_count( $user_id, 1 ); } /** * Helper function used to increase (by one) the count of replies for a user when * a reply is published. * * This is a helper function, hooked to `bbp_new_reply` * * @since 2.6.0 bbPress (r5309) * * @param $topic_id * @param $forum_id * @param $anonymous_data * @param $topic_author */ function bbp_increase_user_reply_count( $reply_id = 0 ) { $user_id = bbp_get_reply_author_id( $reply_id ); return bbp_bump_user_reply_count( $user_id, 1 ); } /** * Helper function used to decrease (by one) the count of topics for a user when * a topic is unpublished. * * @since 2.6.0 bbPress (r5309) * * @param $topic_id */ function bbp_decrease_user_topic_count( $topic_id = 0 ) { $user_id = bbp_get_topic_author_id( $topic_id ); return bbp_bump_user_topic_count( $user_id, -1 ); } /** * Helper function used to increase (by one) the count of replies for a user when * a topic is unpublished. * * @since 2.6.0 bbPress (r5309) * * @param $reply_id */ function bbp_decrease_user_reply_count( $reply_id = 0 ) { $user_id = bbp_get_reply_author_id( $reply_id ); return bbp_bump_user_reply_count( $user_id, -1 ); } /** Permissions ***************************************************************/ /** * Redirect if unauthorized user is attempting to edit another user * * This is hooked to 'bbp_template_redirect' and controls the conditions under * which a user can edit another user (or themselves.) If these conditions are * met, we assume a user cannot perform this task, and look for ways they can * earn the ability to access this template. * * @since 2.1.0 bbPress (r3605) */ function bbp_check_user_edit() { // Bail if not editing a user if ( ! bbp_is_single_user_edit() ) { return; } // Default to false $redirect = true; $user_id = bbp_get_displayed_user_id(); // Allow user to edit their own profile if ( bbp_is_user_home_edit() ) { $redirect = false; // Allow if current user can edit the displayed user } elseif ( current_user_can( 'edit_user', $user_id ) ) { $redirect = false; // Allow if user can manage network users, or edit-any is enabled } elseif ( current_user_can( 'manage_network_users' ) || apply_filters( 'enable_edit_any_user_configuration', false ) ) { $redirect = false; } // Allow conclusion to be overridden $redirect = (bool) apply_filters( 'bbp_check_user_edit', $redirect, $user_id ); // Bail if not redirecting if ( false === $redirect ) { return; } // Filter redirect URL $profile_url = bbp_get_user_profile_url( $user_id ); $redirect_to = apply_filters( 'bbp_check_user_edit_redirect_to', $profile_url, $user_id ); // Redirect bbp_redirect( $redirect_to ); } /** * Check if a user is blocked, or cannot spectate the forums. * * @since 2.0.0 bbPress (r2996) */ function bbp_forum_enforce_blocked() { // Bail if not logged in or keymaster if ( ! is_user_logged_in() || bbp_is_user_keymaster() ) { return; } // Set 404 if in bbPress and user cannot spectate if ( is_bbpress() && ! current_user_can( 'spectate' ) ) { bbp_set_404(); } } /** Sanitization **************************************************************/ /** * Sanitize displayed user data, when viewing and editing any user. * * This somewhat monolithic function handles the escaping and sanitization of * user data for a bbPress profile. There are two reasons this all happens here: * * 1. bbPress took a similar approach to WordPress, and funnels all user profile * data through a central helper. This eventually calls sanitize_user_field() * which applies a few context based filters, which some third party plugins * might be relying on bbPress to play nicely with. * * 2. Early versions of bbPress 2.x templates did not escape this data meaning * a backwards compatible approach like this one was necessary to protect * existing installations that may have custom template parts. * * @since 2.6.0 bbPress (r5368) * * @param string $value * @param string $field * @param string $context * @return string */ function bbp_sanitize_displayed_user_field( $value = '', $field = '', $context = 'display' ) { // Bail if not editing or displaying (maybe we'll do more here later) if ( ! in_array( $context, array( 'edit', 'display' ), true ) ) { return $value; } // By default, no filter set (consider making this an array later) $filter = false; // Big switch statement to decide which user field we're sanitizing and how switch ( $field ) { // Description is a paragraph case 'description' : $filter = ( 'edit' === $context ) ? '' : 'wp_kses_data'; break; // Email addresses are sanitized with a specific function case 'user_email' : $filter = 'sanitize_email'; break; // Name & login fields case 'user_login' : case 'display_name' : case 'first_name' : case 'last_name' : case 'nick_name' : $filter = ( 'edit' === $context ) ? 'esc_attr' : 'esc_html'; break; // wp-includes/default-filters.php escapes this for us via esc_url() case 'user_url' : break; } // Run any applicable filters on the value if ( ! empty( $filter ) ) { $value = call_user_func( $filter, $value ); } return $value; } /** Converter *****************************************************************/ /** * Convert passwords from previous platform encryption to WordPress encryption. * * @since 2.1.0 bbPress (r3813) * @since 2.6.10 bbPress (r7244) Switched from direct query to get_user_by() */ function bbp_user_maybe_convert_pass() { // Sanitize login $login = ! empty( $_POST['log'] ) ? sanitize_user( wp_unslash( $_POST['log'] ) ) : ''; // Sanitize password $pass = ! empty( $_POST['pwd'] ) ? trim( $_POST['pwd'] ) : ''; // Bail if no username or password if ( empty( $login ) || empty( $pass ) ) { return; } // Get user by login... $user = get_user_by( 'login', $login ); // ...or get user by email if ( empty( $user ) && strpos( $login, '@' ) ) { $user = get_user_by( 'email', $login ); } // Bail if no user if ( empty( $user ) ) { return; } // Get converter class from usermeta $class = get_user_meta( $user->ID, '_bbp_class', true ); // Bail if no converter class in meta if ( empty( $class ) || ! is_string( $class ) ) { return; } // Setup the converter bbp_setup_converter(); // Try to instantiate the converter class $converter = bbp_new_converter( $class ); // Bail if no converter if ( empty( $converter ) ) { return; } // Try to call the password conversion callback method if ( ( $converter instanceof BBP_Converter_Base ) && method_exists( $converter, 'callback_pass' ) ) { $converter->callback_pass( $login, $pass ); } } Особенности игрового процесса на реальные средства в интернет-казино – FSConsulting

Особенности игрового процесса на реальные средства в интернет-казино

Pin-up Casino – знаменитая развлекательная платформа, которая имеет огромным числом автоматов с качественным программным обеспечением. Посетителей портала привлекает понятный и комфортный интерфейсом с уникальной визуальными эффектами и обширный каталог игр. К удобства пользователей также акционная система, быстрый вывод выигрышей, план преданности и прочие бонусы.

Причины популярности интернет-площадки.

На нынешнем пространстве досуга онлайн-ресурс удерживает одно из лидирующих положений. Из-за обширному выбору азартных автоматов, заманчивым предложениям, надежной опции получения выигрыша, популярность гэмблинг-платформы все время растет. Данная направленность обусловлена следующими обстоятельствами:

  1. Доступность Для того чтобы стартовать игре на платформе, нужен только устройство и интернет-соединение. В каждой локации мира, на любое возможное время дня, доступно играть в онлайн-казино. Запускать игровые машины вышло еще более удобно, благодаря наличию версии для мобильных устройств.
  2. Обеспеченная охрана. Абсолютное соблюдение правил справедливой игрового процесса и охрана проводимых платежных процессов с использованием инновационных методов криптографии.
  3. Приватность Обеспечение безопасности и секретность персональных информации участника. При игры в деморежиме не требуется даже учетная запись.
  4. Всеобъемлющая акционная система. Применяются бесплатные бесплатные вращения, дополнительные раунды, особые иконки, особенные предложения, бонусы за активность, джекпот-система накопления.
  5. Выбор игровых слотов: игры на столе, игры с картами, обычные фрукты, и игровые автоматы с необычным сюжетом.
  6. Бесплатная развлечение. Создателями предусмотрена демо-версия на игровых аппаратах.
  7. Непрерывная партия. Использование действующего альтернативного адреса, предоставляющего подключение к игре 24 на 7.

Виртуальный клуб и популярные разработчики

Автоматы слоты слоты с живыми дилерами созданы передовыми мировыми поставщиками. Основными создателями гейминг контента для платформы становятся такие бренды: Thunderkick, Microgaming, Triple Edge Studios, Gacha Studios, Kalamba Games, Pragmatic Play, BetSoft и другие. В игровой пространство регулярно добавляются новинки, модернизируются предыдущие версии.

Главную часть казино представляют традиционные и новейшие игровые автоматы. Ретро слоты включают незамысловатые правила развлечения, дополнительные раунды и игру на риск. Чрезвычайно популярные из них: Crazy Monkey, Book of Ra Deluxe, Fruit Cocktail, Lucky Haunter, Island. В базе развлекательных автоматов находится генератор произвольных чисел. Актуальные машины характеризует разнообразие тем, обилие линий и др.. Однорукие бандиты содержат разнообразными призовыми функциями. Так, игровые автоматы, разработанные фирмой Microgaming, имеют систему нарастающих призов. Для игр от Playtech присущи дополнительные раунды.

Особым категорией гейминг-зала представлены и онлайн-трансляции. Эти игры осуществляются в моде реального времени под руководством крупье. При этом существует настоящее коммуникация участников друг с другом и с ведущим. Данные азартные игры доступны следующими типами: рулетка (евро, американо), двадцать одно (классический с дополнительными пари, мультиплеерный), пунто банко (классическая), карточная игра (трехкарточный, карибский) и другие. Выполняется регулярное модернизация ПО. У игрищ в формате реального тайминга не предусмотрен тестового формата. Доступен только старт на реальные средства.

Доступны новые, именуемые мгновенные развлечения, такие как Авиатор. Ихняя особенность проявляется в том, что у данных игр нет катушек, иконок, выплатных линий. Участникам нужно быстрое принятие о выводе денежных средств, если нет, то возможно потерять всё. Преимуществом становится способность совершать ряд ставок одновременно, чем возможно значительно приумножить прибыль при положительном результате. Развлечение — простая, всё же она запрашивает от геймера сосредоточенности и быстрой реакции.

Автоматы слоты подобраны по определенному правилу, чтобы у каждого был высокий процент возврата. RTP слот-машин в виртуальных казино составляет от 95 до 98 процентов.

Для комфорта игрока на веб-ресурсе в строке поиска реализована возможность сортировки игровых автоматов по нескольким параметрам: провайдерам, жанрам, оценке и т.д. Всякий участник может заносить избранную игрушку в список предпочтений, что также создаёт пребывание на сайте более комфортным.

Зеркало официального сайта азартного клуба

В отдельных ситуациях основной ресурс виртуального казино может стать недоступным для игроков. Это происходит из-за блокировки провайдера, нападения хакеров, выполнения техобслуживания или перегрузки сервера из-за множества игроков. Другой вход к сайту предоставляет рабочее дубликат. Это дубликат сайта с аналогичными возможностями и возможностями, но с другим URL-адресом. На текущем зеркале геймерам возможно создание учетной записи, пополнение баланса, вывод денежных средств, участие в игре. На альтернативном сайте за клиентом сохраняются акционные предложения, поощрения, сервис технической поддержки, возможность просмотра статистики игр и иное.

Отыскать URL действующего альтернативного сайта можно с помощью техподдержки портала, используя поисковика, в информационной рассылке или соцсетях.

Имеются и прочие методы обхождения блокировки ресурса, которые обеспечивают беспрерывный круглосуточный вход к играм на платформе.

  1. Применение VPN, дающее возможность сменить IP-адрес через альтернативного сервера.
  2. Применение прокси, обходящих блокировку.
  3. Настройка DNS параметров на ПК или иного устройстве.

Для гарантирования стабильного работы платформы реальных зеркал может быть несколько, что делает геймплей максимально комфортной для игроков.

Каким образом играть безвозмездно

Демо режим в интернет-казино Pin-up Casino предоставляет возможность участия в игре без затрат собственных средств. Он подходит начинающим, которые стремятся понять основы автомата, изучить навигацией, освоить характеристики аппарата без финансовых потерь. Также тестовые версии способны включать и бывалые геймеры.

Игра в пробной версии происходит на фантики монеты. Туров может быть значительное количество. В случае, если коины исчерпываются, баланс без труда восстанавливается. С целью этой задачи требуется обновить игровое приложение, впоследствии можно продолжить тестировать слотовую машину. Забрать приз в демонстрационном варианте невозможно. Исследовав слоты, испытав определенную тактику, и проверив ее результативность, можно приступать к регистрации аккаунта.

Тренировочный вариант помогает получить умений для участия в главном формате. Среди прочих преимуществ бесплатной версии слотов:

Принципы безопасной игры в онлайн-казино Pin-up Casino.

Любой участники, участвующие в азартных играх на средства в виртуальных казино с акциями, обязаны придерживаться установленные нормы. Комплект подобных правил возможно ознакомиться с на главной страничке портала в разделе «Ответственная игра». Придерживание их отслеживается фирмой сразу же на платформе:

  1. Зарегистрироваться на веб-ресурсе и включаться в развлечении могут только индивиды, достигнувшие 18+. Мониторинг проводится благодаря проверки и распознавания.
  2. Открыть на портале можно только один профиль. Проверка проводится во время идентификации личности.
  3. Пользователям на платформе важно определять для себя лимиты на финансы и период. Данное способствует предотвратить денежных проблем и пристрастия. Таким образом функционирует механизм самоограничения.
  4. Геймеры должны изучить и осознавать условия игры. Оценивать перспективы триумфа и опасности поражения. В конкретных обстоятельствах необходимо формальное подтверждение знания определённых правил.
  5. Пользователи могут подать запрос с просьбой к администрации игорного дома о ограничении аккаунта к игровому залу на срок от 6 месяцев.

В свою линию сайт необходимо способствовать принципам честной игры в области онлайн-казино. Площадка представляет собой официальным игровым домом, с лицензией разрешение Кюрасао на оказание сервисов в области азартных игр. Нормы, которые выполняет онлайн-казино в рамках честной игры таковы:

  1. Использование сертифицированных игровых устройств. Информация не передаются третьим лицам. Обеспечен выплата выигрыша в заданные сроки.
  2. Коллективная обязанность, какая содействует избежанию лудомании.
  3. Применение технологии защиты. Секретность входа, сбережения и применения личных данных.
  4. Зашифровка и охрана монетарных сделок. Применение новейших методов защиты сделок.

Игровые игры на средства на платформе Pin-up Casino

Цель всякого игрока, который попадает на сайт площадки, — азарт на деньги. Для того чтобы открыть доступ к игре, нужно зарегистрировать личный аккаунт. Создание аккаунта осуществляется мгновенно и не требует значительного времени. Запреты в учетной записи имеют индивиды, не перешагнувшие 18-летнего возраста. С целью открытия персонального кабинета требуется выбрать один из способов, с помощью которого он будет оформлен. Это может быть может быть смартфон, электронная почта либо мессенджер. Оформление профиля состоит в себя различных шагов:

  1. Вход на центральную веб-страницу площадки.
  2. Переход на вкладку бланка для создания аккаунта.
  3. Подбор варианта создания игрового учетной записи.
  4. Подготовка формы с индивидуальными сведениями.
  5. Нажатие на клавишу «Зарегистрироваться».

Открыть личный профиль с помощью социальные сети становится легче. Всего лишь определить современную социальную сеть, в где у пользователя есть профиль, и залогиниться через неё.

По окончании регистрации становится доступен входа в профиль пользователя. Авторизовавшись в свой профиль, игрок имеет возможность воспользоваться разнообразными возможностями казино платформы. В её распоряжении добавление казино баланса, активация призовых предложений, участие в турнирах, акциях и тиражах, выполнение идентификационной процесса, снятие выигрышей и многое другое. Пополнение счета — это типичная манипуляция, не порождающая трудностей у пользователей. Депонировать финансы и выводить деньги можно с помощью той же самой платежного сервиса. Пополнение выполняется сразу, в рамках установленных наименьших ограничений.

Снятие средств из онлайн-казино состоит из рядом шагов:

  1. Доступ в секцию «Касса».
  2. Включение функции «Вывести выигрыш».
  3. Определение метода оплаты.
  4. Выбор сведений трансфера и размера выплачиваемых финансов.
  5. Одобрение действий.

Снятие денег неосуществим в отсутствие этапа верификации. Аутентификация заключается в подтверждении персоны через отправки индивидуальных бумаг. Выполняется верификация года игрока и наличия уникального профиля. В случае, если при процедуре подтверждения личности найдены погрешности или неточности, учетная запись и игровой счет будут приостановлены.

Заявки на снятие денежных средств исполняются мгновенно. Пополнение требует определенное время. Длительность процесса обусловлена от заданного метода вычисления. Имеет значение порядок очередности и объем выплачиваемых денег. Когда переводится большая выплата, операция потребует больше времени. Возможно иметься дополнительный комиссия из-за финансовых платформ. С целью выведения задействуются аналогичные способы, что и для увеличения аккаунта в казино. Данное правило вступает в силу для обеспечения защищенности. Каждый метод содержит лимиты по минимальной и максимум размеру вывода средств, с этой данными можно изучить в особом секции на официальном сайте игорного заведения.

В отдельных случаях вывод денег становится недоступным. Факторами данного состояния выступают:

Премиальная схема сайта

Официальная платформа предлагает привлекательную программу поощрений и вознаграждений. Премиальная политика рассчитана на новичков, а также на постоянных клиентов. Начинающим игрокам предоставляются бонусы за стартовые вклады. Вознаграждением для регулярных клиентов является часть от депозитных внесений и бесплатные вращения. Чтобы получить этого подарка нужно пополнение заданной количества финансов на депозитный баланс.

Безвозмездные вращения (бесплатные спины) предназначены для игры в интернет-слоты. Фриспины также допустимо удачно применять для развлечения в новые слоты. Выгода заключается в том, что можно параллельно и познакомиться с свежим игровым автоматом, и получить выигрыш. Для снятия заработанного из безвозмездных раскруток вознаграждения, необходим проигрыш. Отрабатывать премию оптимально в техасский холдем, двадцать одно, покерный автомат или казино рулетку.

В возможностях геймеров также предложения, чемпионаты, разыгрыши кушев, Колесо Удачи, вознаграждения по промокоду. На систематической базе устраиваются специальные турниры. Извещение о текущих акциях и начале соревнований приходит в профиль пользователя геймера или приходит по e-mail, если есть подписка на информационную рассылку.

Регулярных участников поддерживают кэшбэком. Его величина обусловлен от количества потерянных средств за определённого отрезка времени. Часть часть убытков компенсируется на аккаунт в виде реальных денег или кредитов, что достаточно удобно.

Сервис обладает отличную систему лояльности, в которой пользователи получают баллы. Продвижение с уровня на этап сопровождается предложением плюшек. Участники с максимальным числом очков приобретают статус VIP-клиентов. Такие участники получают самые большие вознаграждения и сувениры, особые положения для снятия выигрыша, участия в состязаниях, скидки, возврат средств и прочее.

Мобильная версия и аппликация площадки Pin-up Casino

Для тех, кто ценителей играть в азартные игры со мобильных устройств и планшетов, создана мобильная мобильная платформа. Данная система адаптирована для габариты тачскрина. Обеспечивается легкая загружаемость сайта из любых интернет-браузеров. Для того чтобы пользоваться интернет-казино на телефонах, нет необходимости в загрузка и установка аппа, что является удобным и экономит время. Достаточно несложно набрать URL игровой платформы в строке поиска. В том случае, когда хозяин девайса сам решил инсталлировать официальное программу, можно скачать файл установки для Android и iOS, с основной страницы официального веб-сайта. Приложение также удобно тем, что по сравнению с веб-ресурса, не ограничивается и дает возможность геймить непрерывно.

Портативная вариант обладает комфортный интерфейс и идентичный основной версии набор функций. Сыграть с портативного гаджета несложно и комфортно. В непосредственном доступе все доступные игровые автоматы и аттракционы ресурса. Портативная версия обеспечивает те же степени секьюрности, что и настольная. Вся приватная информация и информация монетарных транзакций обезопасены безопасным шифровкой.

В случае появления различных запросов, менеджментом игорного дома обеспечена непрерывная техническая поддержка. Если проблема нуждается в срочного решения, рекомендуется обратиться к техподдержкой посредством звонка на горячую линию или написать в чат-боте. Решение проблемы реально в процессе азартного развлечения. Учетный пользователь имеет возможность оставить запрос в аккаунте. По цифровой почте предлагается спрашивать запросы, которые требуют детального рассмотрения. Эксперты техподдержки откликаются на вопросы, касающиеся регистрацией, пополнением баланса, обналичиванием выигрыша, загрузкой фирменного софта, условиями игры и прочими вопросами.

Pin-up Casino — известное интернет-казино, которое предоставляет огромный выбор развлечений, широкую систему поощрений и надежную помощь. Создайте аккаунт прямо сейчас, пополняйте аккаунт, запускайте слоты в интернете на реальные средства и побеждайте.