/** * WooCommerce Customer Functions * * Functions for customers. * * @package WooCommerce\Functions * @version 2.2.0 */ use Automattic\WooCommerce\Enums\OrderInternalStatus; use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore; use Automattic\WooCommerce\Internal\Utilities\Users; use Automattic\WooCommerce\Utilities\OrderUtil; defined( 'ABSPATH' ) || exit; /** * Prevent any user who cannot 'edit_posts' (subscribers, customers etc) from seeing the admin bar. * * Note: get_option( 'woocommerce_lock_down_admin', true ) is a deprecated option here for backwards compatibility. Defaults to true. * * @param bool $show_admin_bar If should display admin bar. * @return bool */ function wc_disable_admin_bar( $show_admin_bar ) { /** * Controls whether the WooCommerce admin bar should be disabled. * * @since 3.0.0 * * @param bool $enabled */ if ( apply_filters( 'woocommerce_disable_admin_bar', true ) && ! ( current_user_can( 'edit_posts' ) || current_user_can( 'manage_woocommerce' ) ) ) { $show_admin_bar = false; } return $show_admin_bar; } add_filter( 'show_admin_bar', 'wc_disable_admin_bar', 10, 1 ); // phpcs:ignore WordPress.VIP.AdminBarRemoval.RemovalDetected if ( ! function_exists( 'wc_create_new_customer' ) ) { /** * Create a new customer. * * @since 9.4.0 Moved woocommerce_registration_error_email_exists filter to the shortcode checkout class. * @since 9.4.0 Removed handling for generating username/password based on settings--this is consumed at form level. Here, if data is missing it will be generated. * * @param string $email Customer email. * @param string $username Customer username. * @param string $password Customer password. * @param array $args List of arguments to pass to `wp_insert_user()`. * @return int|WP_Error Returns WP_Error on failure, Int (user ID) on success. */ function wc_create_new_customer( $email, $username = '', $password = '', $args = array() ) { if ( empty( $email ) || ! is_email( $email ) ) { return new WP_Error( 'registration-error-invalid-email', __( 'Please provide a valid email address.', 'woocommerce' ) ); } if ( email_exists( $email ) ) { return new WP_Error( 'registration-error-email-exists', sprintf( // Translators: %s Email address. esc_html__( 'An account is already registered with %s. Please log in or use a different email address.', 'woocommerce' ), esc_html( $email ) ) ); } if ( empty( $username ) ) { $username = wc_create_new_customer_username( $email, $args ); } $username = sanitize_user( $username ); if ( empty( $username ) || ! validate_username( $username ) ) { return new WP_Error( 'registration-error-invalid-username', __( 'Please provide a valid account username.', 'woocommerce' ) ); } if ( username_exists( $username ) ) { return new WP_Error( 'registration-error-username-exists', __( 'An account is already registered with that username. Please choose another.', 'woocommerce' ) ); } // Handle password creation. $password_generated = false; if ( empty( $password ) ) { $password = wp_generate_password(); $password_generated = true; } if ( empty( $password ) ) { return new WP_Error( 'registration-error-missing-password', __( 'Please create a password for your account.', 'woocommerce' ) ); } // Use WP_Error to handle registration errors. $errors = new WP_Error(); /** * Fires before a customer account is registered. * * This hook fires before customer accounts are created and passes the form data (username, email) and an array * of errors. * * This could be used to add extra validation logic and append errors to the array. * * @since 7.2.0 * * @internal Matches filter name in WooCommerce core. * * @param string $username Customer username. * @param string $user_email Customer email address. * @param \WP_Error $errors Error object. */ do_action( 'woocommerce_register_post', $username, $email, $errors ); /** * Filters registration errors before a customer account is registered. * * This hook filters registration errors. This can be used to manipulate the array of errors before * they are displayed. * * @since 7.2.0 * * @internal Matches filter name in WooCommerce core. * * @param \WP_Error $errors Error object. * @param string $username Customer username. * @param string $user_email Customer email address. * @return \WP_Error */ $errors = apply_filters( 'woocommerce_registration_errors', $errors, $username, $email ); if ( is_wp_error( $errors ) && $errors->get_error_code() ) { return $errors; } // Merged passed args with sanitized username, email, and password. $customer_data = array_merge( $args, array( 'user_login' => $username, 'user_pass' => $password, 'user_email' => $email, 'role' => 'customer', ) ); /** * Filters customer data before a customer account is registered. * * This hook filters customer data. It allows user data to be changed, for example, username, password, email, * first name, last name, and role. * * @since 7.2.0 * * @param array $customer_data An array of customer (user) data. * @return array */ $new_customer_data = apply_filters( 'woocommerce_new_customer_data', wp_parse_args( $customer_data, array( 'first_name' => '', 'last_name' => '', 'source' => 'unknown', ) ) ); $customer_id = wp_insert_user( $new_customer_data ); if ( is_wp_error( $customer_id ) ) { return $customer_id; } // Set account flag to remind customer to update generated password. if ( $password_generated ) { update_user_option( $customer_id, 'default_password_nag', true, true ); } /** * Fires after a customer account has been registered. * * This hook fires after customer accounts are created and passes the customer data. * * @since 7.2.0 * * @internal Matches filter name in WooCommerce core. * * @param integer $customer_id New customer (user) ID. * @param array $new_customer_data Array of customer (user) data. * @param string $password_generated The generated password for the account. */ do_action( 'woocommerce_created_customer', $customer_id, $new_customer_data, $password_generated ); return $customer_id; } } /** * Create a unique username for a new customer. * * @since 3.6.0 * @param string $email New customer email address. * @param array $new_user_args Array of new user args, maybe including first and last names. * @param string $suffix Append string to username to make it unique. * @return string Generated username. */ function wc_create_new_customer_username( $email, $new_user_args = array(), $suffix = '' ) { $username_parts = array(); if ( isset( $new_user_args['first_name'] ) ) { $username_parts[] = sanitize_user( $new_user_args['first_name'], true ); } if ( isset( $new_user_args['last_name'] ) ) { $username_parts[] = sanitize_user( $new_user_args['last_name'], true ); } // Remove empty parts. $username_parts = array_filter( $username_parts ); // If there are no parts, e.g. name had unicode chars, or was not provided, fallback to email. if ( empty( $username_parts ) ) { $email_parts = explode( '@', $email ); $email_username = $email_parts[0]; // Exclude common prefixes. if ( in_array( $email_username, array( 'sales', 'hello', 'mail', 'contact', 'info', ), true ) ) { // Get the domain part. $email_username = $email_parts[1]; } $username_parts[] = sanitize_user( $email_username, true ); } $username = wc_strtolower( implode( '.', $username_parts ) ); if ( $suffix ) { $username .= $suffix; } /** * WordPress 4.4 - filters the list of blocked usernames. * * @since 3.7.0 * @param array $usernames Array of blocked usernames. */ $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() ); // Stop illegal logins and generate a new random username. if ( in_array( strtolower( $username ), array_map( 'strtolower', $illegal_logins ), true ) ) { $new_args = array(); /** * Filter generated customer username. * * @since 3.7.0 * @param string $username Generated username. * @param string $email New customer email address. * @param array $new_user_args Array of new user args, maybe including first and last names. * @param string $suffix Append string to username to make it unique. */ $new_args['first_name'] = apply_filters( 'woocommerce_generated_customer_username', 'woo_user_' . zeroise( wp_rand( 0, 9999 ), 4 ), $email, $new_user_args, $suffix ); return wc_create_new_customer_username( $email, $new_args, $suffix ); } if ( username_exists( $username ) ) { // Generate something unique to append to the username in case of a conflict with another user. $suffix = '-' . zeroise( wp_rand( 0, 9999 ), 4 ); return wc_create_new_customer_username( $email, $new_user_args, $suffix ); } /** * Filter new customer username. * * @since 3.7.0 * @param string $username Customer username. * @param string $email New customer email address. * @param array $new_user_args Array of new user args, maybe including first and last names. * @param string $suffix Append string to username to make it unique. */ return apply_filters( 'woocommerce_new_customer_username', $username, $email, $new_user_args, $suffix ); } /** * Login a customer (set auth cookie and set global user object). * * @param int $customer_id Customer ID. */ function wc_set_customer_auth_cookie( $customer_id ) { wp_set_current_user( $customer_id ); wp_set_auth_cookie( $customer_id, true ); // Update session. if ( is_callable( array( WC()->session, 'init_session_cookie' ) ) ) { WC()->session->init_session_cookie(); } } /** * Get past orders (by email) and update them. * * @param int $customer_id Customer ID. * @return int */ function wc_update_new_customer_past_orders( $customer_id ) { $linked = 0; $complete = 0; $customer = get_user_by( 'id', absint( $customer_id ) ); $customer_orders = wc_get_orders( array( 'limit' => -1, 'customer' => array( array( 0, $customer->user_email ) ), 'return' => 'ids', ) ); if ( ! empty( $customer_orders ) ) { foreach ( $customer_orders as $order_id ) { $order = wc_get_order( $order_id ); if ( ! $order ) { continue; } $order->set_customer_id( $customer->ID ); $order->save(); if ( $order->has_downloadable_item() ) { $data_store = WC_Data_Store::load( 'customer-download' ); $data_store->delete_by_order_id( $order->get_id() ); wc_downloadable_product_permissions( $order->get_id(), true ); } do_action( 'woocommerce_update_new_customer_past_order', $order_id, $customer ); if ( $order->get_status() === OrderInternalStatus::COMPLETED ) { ++$complete; } ++$linked; } } if ( $complete ) { update_user_meta( $customer_id, 'paying_customer', 1 ); Users::update_site_user_meta( $customer_id, 'wc_order_count', '' ); Users::update_site_user_meta( $customer_id, 'wc_money_spent', '' ); Users::delete_site_user_meta( $customer_id, 'wc_last_order' ); } return $linked; } /** * Order payment completed - This is a paying customer. * * @param int $order_id Order ID. */ function wc_paying_customer( $order_id ) { $order = wc_get_order( $order_id ); $customer_id = $order->get_customer_id(); if ( $customer_id > 0 && 'shop_order_refund' !== $order->get_type() ) { $customer = new WC_Customer( $customer_id ); if ( ! $customer->get_is_paying_customer() ) { $customer->set_is_paying_customer( true ); $customer->save(); } } } add_action( 'woocommerce_payment_complete', 'wc_paying_customer' ); add_action( 'woocommerce_order_status_completed', 'wc_paying_customer' ); /** * Checks if a user (by email or ID or both) has bought an item. * * @param string $customer_email Customer email to check. * @param int $user_id User ID to check. * @param int $product_id Product ID to check. * @return bool */ function wc_customer_bought_product( $customer_email, $user_id, $product_id ) { global $wpdb; $result = apply_filters( 'woocommerce_pre_customer_bought_product', null, $customer_email, $user_id, $product_id ); if ( null !== $result ) { return $result; } /** * Whether to use lookup tables - it can optimize performance, but correctness depends on the frequency of the AS job. * * @since 9.7.0 * * @param bool $enabled * @param string $customer_email Customer email to check. * @param int $user_id User ID to check. * @param int $product_id Product ID to check. * @return bool */ $use_lookup_tables = apply_filters( 'woocommerce_customer_bought_product_use_lookup_tables', false, $customer_email, $user_id, $product_id ); $transient_name = 'wc_customer_bought_product_' . md5( $customer_email . $user_id . $use_lookup_tables ); if ( $use_lookup_tables ) { // Lookup tables get refreshed along with the `woocommerce_reports` transient version. $transient_version = WC_Cache_Helper::get_transient_version( 'woocommerce_reports' ); } else { $transient_version = WC_Cache_Helper::get_transient_version( 'orders' ); } $transient_value = get_transient( $transient_name ); if ( isset( $transient_value['value'], $transient_value['version'] ) && $transient_value['version'] === $transient_version ) { $result = $transient_value['value']; } else { $customer_data = array( $user_id ); if ( $user_id ) { $user = get_user_by( 'id', $user_id ); if ( isset( $user->user_email ) ) { $customer_data[] = $user->user_email; } } if ( is_email( $customer_email ) ) { $customer_data[] = $customer_email; } $customer_data = array_map( 'esc_sql', array_filter( array_unique( $customer_data ) ) ); $statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() ); if ( count( $customer_data ) === 0 ) { return false; } if ( OrderUtil::custom_orders_table_usage_is_enabled() ) { $statuses = array_map( function ( $status ) { return "wc-$status"; }, $statuses ); $order_table = OrdersTableDataStore::get_orders_table_name(); $user_id_clause = ''; if ( $user_id ) { $user_id_clause = 'OR o.customer_id = ' . absint( $user_id ); } if ( $use_lookup_tables ) { // HPOS: yes, Lookup table: yes. $sql = " SELECT DISTINCT product_or_variation_id FROM ( SELECT CASE WHEN product_id != 0 THEN product_id ELSE variation_id END AS product_or_variation_id FROM {$wpdb->prefix}wc_order_product_lookup lookup INNER JOIN $order_table AS o ON lookup.order_id = o.ID WHERE o.status IN ('" . implode( "','", $statuses ) . "') AND ( o.billing_email IN ('" . implode( "','", $customer_data ) . "') $user_id_clause ) ) AS subquery WHERE product_or_variation_id != 0 "; } else { // HPOS: yes, Lookup table: no. $sql = " SELECT DISTINCT im.meta_value FROM $order_table AS o INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON o.id = i.order_id INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id WHERE o.status IN ('" . implode( "','", $statuses ) . "') AND im.meta_key IN ('_product_id', '_variation_id' ) AND im.meta_value != 0 AND ( o.billing_email IN ('" . implode( "','", $customer_data ) . "') $user_id_clause ) "; } $result = $wpdb->get_col( $sql ); } elseif ( $use_lookup_tables ) { // HPOS: no, Lookup table: yes. $result = $wpdb->get_col( " SELECT DISTINCT product_or_variation_id FROM ( SELECT CASE WHEN lookup.product_id != 0 THEN lookup.product_id ELSE lookup.variation_id END AS product_or_variation_id FROM {$wpdb->prefix}wc_order_product_lookup AS lookup INNER JOIN {$wpdb->posts} AS p ON p.ID = lookup.order_id INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' ) AND pm.meta_key IN ( '_billing_email', '_customer_user' ) AND pm.meta_value IN ( '" . implode( "','", $customer_data ) . "' ) ) AS subquery WHERE product_or_variation_id != 0 " ); // WPCS: unprepared SQL ok. } else { // HPOS: no, Lookup table: no. // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared $result = $wpdb->get_col( " SELECT DISTINCT im.meta_value FROM {$wpdb->posts} AS p INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON p.ID = i.order_id INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' ) AND pm.meta_key IN ( '_billing_email', '_customer_user' ) AND im.meta_key IN ( '_product_id', '_variation_id' ) AND im.meta_value != 0 AND pm.meta_value IN ( '" . implode( "','", $customer_data ) . "' ) " ); // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared } $result = array_map( 'absint', $result ); $transient_value = array( 'version' => $transient_version, 'value' => $result, ); set_transient( $transient_name, $transient_value, DAY_IN_SECONDS * 30 ); } return in_array( absint( $product_id ), $result, true ); } /** * Checks if the current user has a role. * * @param string $role The role. * @return bool */ function wc_current_user_has_role( $role ) { return wc_user_has_role( wp_get_current_user(), $role ); } /** * Checks if a user has a role. * * @param int|\WP_User $user The user. * @param string $role The role. * @return bool */ function wc_user_has_role( $user, $role ) { if ( ! is_object( $user ) ) { $user = get_userdata( $user ); } if ( ! $user || ! $user->exists() ) { return false; } return in_array( $role, $user->roles, true ); } /** * Checks if a user has a certain capability. * * @param array $allcaps All capabilities. * @param array $caps Capabilities. * @param array $args Arguments. * * @return array The filtered array of all capabilities. */ function wc_customer_has_capability( $allcaps, $caps, $args ) { if ( isset( $caps[0] ) ) { switch ( $caps[0] ) { case 'view_order': $user_id = intval( $args[1] ); $order = wc_get_order( $args[2] ); if ( $order && $user_id === $order->get_user_id() ) { $allcaps['view_order'] = true; } break; case 'pay_for_order': $user_id = intval( $args[1] ); $order_id = isset( $args[2] ) ? $args[2] : null; // When no order ID, we assume it's a new order // and thus, customer can pay for it. if ( ! $order_id ) { $allcaps['pay_for_order'] = true; break; } $order = wc_get_order( $order_id ); if ( $order && ( $user_id === $order->get_user_id() || ! $order->get_user_id() ) ) { $allcaps['pay_for_order'] = true; } break; case 'order_again': $user_id = intval( $args[1] ); $order = wc_get_order( $args[2] ); if ( $order && $user_id === $order->get_user_id() ) { $allcaps['order_again'] = true; } break; case 'cancel_order': $user_id = intval( $args[1] ); $order = wc_get_order( $args[2] ); if ( $order && $user_id === $order->get_user_id() ) { $allcaps['cancel_order'] = true; } break; case 'download_file': $user_id = intval( $args[1] ); $download = $args[2]; if ( $download && $user_id === $download->get_user_id() ) { $allcaps['download_file'] = true; } break; } } return $allcaps; } add_filter( 'user_has_cap', 'wc_customer_has_capability', 10, 3 ); /** * Safe way of allowing shop managers restricted capabilities that will remove * access to the capabilities if WooCommerce is deactivated. * * @since 3.5.4 * @param bool[] $allcaps Array of key/value pairs where keys represent a capability name and boolean values * represent whether the user has that capability. * @param string[] $caps Required primitive capabilities for the requested capability. * @param array $args Arguments that accompany the requested capability check. * @param WP_User $user The user object. * @return bool[] */ function wc_shop_manager_has_capability( $allcaps, $caps, $args, $user ) { if ( wc_user_has_role( $user, 'shop_manager' ) ) { // @see wc_modify_map_meta_cap, which limits editing to customers. $allcaps['edit_users'] = true; } return $allcaps; } add_filter( 'user_has_cap', 'wc_shop_manager_has_capability', 10, 4 ); /** * Modify the list of editable roles to prevent non-admin adding admin users. * * @param array $roles Roles. * @return array */ function wc_modify_editable_roles( $roles ) { if ( is_multisite() && is_super_admin() ) { return $roles; } if ( ! wc_current_user_has_role( 'administrator' ) ) { unset( $roles['administrator'] ); if ( wc_current_user_has_role( 'shop_manager' ) ) { $shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ); return array_intersect_key( $roles, array_flip( $shop_manager_editable_roles ) ); } } return $roles; } add_filter( 'editable_roles', 'wc_modify_editable_roles' ); /** * Modify capabilities to prevent non-admin users editing admin users. * * $args[0] will be the user being edited in this case. * * @param array $caps Array of caps. * @param string $cap Name of the cap we are checking. * @param int $user_id ID of the user being checked against. * @param array $args Arguments. * @return array */ function wc_modify_map_meta_cap( $caps, $cap, $user_id, $args ) { if ( is_multisite() && is_super_admin() ) { return $caps; } switch ( $cap ) { case 'edit_user': case 'remove_user': case 'promote_user': case 'delete_user': if ( ! isset( $args[0] ) || $args[0] === $user_id ) { break; } elseif ( ! wc_current_user_has_role( 'administrator' ) ) { if ( wc_user_has_role( $args[0], 'administrator' ) ) { $caps[] = 'do_not_allow'; } elseif ( wc_current_user_has_role( 'shop_manager' ) ) { // Shop managers can only edit customer info. $userdata = get_userdata( $args[0] ); $shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment if ( property_exists( $userdata, 'roles' ) && ! empty( $userdata->roles ) && ! array_intersect( $userdata->roles, $shop_manager_editable_roles ) ) { $caps[] = 'do_not_allow'; } } } break; } return $caps; } add_filter( 'map_meta_cap', 'wc_modify_map_meta_cap', 10, 4 ); /** * Get customer download permissions from the database. * * @param int $customer_id Customer/User ID. * @return array */ function wc_get_customer_download_permissions( $customer_id ) { $data_store = WC_Data_Store::load( 'customer-download' ); return apply_filters( 'woocommerce_permission_list', $data_store->get_downloads_for_customer( $customer_id ), $customer_id ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment } /** * Get customer available downloads. * * @param int $customer_id Customer/User ID. * @return array */ function wc_get_customer_available_downloads( $customer_id ) { $downloads = array(); $_product = null; $order = null; $file_number = 0; // Get results from valid orders only. $results = wc_get_customer_download_permissions( $customer_id ); if ( $results ) { foreach ( $results as $result ) { $order_id = intval( $result->order_id ); if ( ! $order || $order->get_id() !== $order_id ) { // New order. $order = wc_get_order( $order_id ); $_product = null; } // Make sure the order exists for this download. if ( ! $order ) { continue; } // Check if downloads are permitted. if ( ! $order->is_download_permitted() ) { continue; } $product_id = intval( $result->product_id ); if ( ! $_product || $_product->get_id() !== $product_id ) { // New product. $file_number = 0; $_product = wc_get_product( $product_id ); } // Check product exists and has the file. if ( ! $_product || ! $_product->exists() || ! $_product->has_file( $result->download_id ) ) { continue; } $download_file = $_product->get_file( $result->download_id ); // If the downloadable file has been disabled (it may be located in an untrusted location) then do not return it. if ( ! $download_file->get_enabled() ) { continue; } // Download name will be 'Product Name' for products with a single downloadable file, and 'Product Name - File X' for products with multiple files. // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment $download_name = apply_filters( 'woocommerce_downloadable_product_name', $download_file['name'], $_product, $result->download_id, $file_number ); $downloads[] = array( 'download_url' => add_query_arg( array( 'download_file' => $product_id, 'order' => $result->order_key, 'email' => rawurlencode( $result->user_email ), 'key' => $result->download_id, ), home_url( '/' ) ), 'download_id' => $result->download_id, 'product_id' => $_product->get_id(), 'product_name' => $_product->get_name(), 'product_url' => $_product->is_visible() ? $_product->get_permalink() : '', // Since 3.3.0. 'download_name' => $download_name, 'order_id' => $order->get_id(), 'order_key' => $order->get_order_key(), 'downloads_remaining' => $result->downloads_remaining, 'access_expires' => $result->access_expires, 'file' => array( 'name' => $download_file->get_name(), 'file' => $download_file->get_file(), ), ); ++$file_number; } } // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment return apply_filters( 'woocommerce_customer_available_downloads', $downloads, $customer_id ); } /** * Get total spent by customer. * * @param int $user_id User ID. * @return string */ function wc_get_customer_total_spent( $user_id ) { $customer = new WC_Customer( $user_id ); return $customer->get_total_spent(); } /** * Get total orders by customer. * * @param int $user_id User ID. * @return int */ function wc_get_customer_order_count( $user_id ) { $customer = new WC_Customer( $user_id ); return $customer->get_order_count(); } /** * Reset _customer_user on orders when a user is deleted. * * @param int $user_id User ID. */ function wc_reset_order_customer_id_on_deleted_user( $user_id ) { global $wpdb; if ( OrderUtil::custom_orders_table_usage_is_enabled() ) { $order_table_ds = wc_get_container()->get( OrdersTableDataStore::class ); $order_table = $order_table_ds::get_orders_table_name(); $wpdb->update( $order_table, array( 'customer_id' => 0, 'date_updated_gmt' => current_time( 'mysql', true ), ), array( 'customer_id' => $user_id, ), array( '%d', '%s', ), array( '%d', ) ); } if ( ! OrderUtil::custom_orders_table_usage_is_enabled() || OrderUtil::is_custom_order_tables_in_sync() ) { $wpdb->update( $wpdb->postmeta, array( 'meta_value' => 0, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ), array( 'meta_key' => '_customer_user', //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => $user_id, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ) ); } } add_action( 'deleted_user', 'wc_reset_order_customer_id_on_deleted_user' ); /** * Get review verification status. * * @param int $comment_id Comment ID. * @return bool */ function wc_review_is_from_verified_owner( $comment_id ) { $verified = get_comment_meta( $comment_id, 'verified', true ); return '' === $verified ? WC_Comments::add_comment_purchase_verification( $comment_id ) : (bool) $verified; } /** * Disable author archives for customers. * * @since 2.5.0 */ function wc_disable_author_archives_for_customers() { global $author; if ( is_author() ) { $user = get_user_by( 'id', $author ); if ( user_can( $user, 'customer' ) && ! user_can( $user, 'edit_posts' ) ) { wp_safe_redirect( wc_get_page_permalink( 'shop' ) ); exit; } } } add_action( 'template_redirect', 'wc_disable_author_archives_for_customers' ); /** * Hooks into the `profile_update` hook to set the user last updated timestamp. * * @since 2.6.0 * @param int $user_id The user that was updated. * @param array $old The profile fields pre-change. */ function wc_update_profile_last_update_time( $user_id, $old ) { wc_set_user_last_update_time( $user_id ); } add_action( 'profile_update', 'wc_update_profile_last_update_time', 10, 2 ); /** * Hooks into the update user meta function to set the user last updated timestamp. * * @since 2.6.0 * @param int $meta_id ID of the meta object that was changed. * @param int $user_id The user that was updated. * @param string $meta_key Name of the meta key that was changed. * @param mixed $_meta_value Value of the meta that was changed. */ function wc_meta_update_last_update_time( $meta_id, $user_id, $meta_key, $_meta_value ) { $keys_to_track = apply_filters( 'woocommerce_user_last_update_fields', array( 'first_name', 'last_name' ) ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment $update_time = in_array( $meta_key, $keys_to_track, true ) ? true : false; $update_time = 'billing_' === substr( $meta_key, 0, 8 ) ? true : $update_time; $update_time = 'shipping_' === substr( $meta_key, 0, 9 ) ? true : $update_time; if ( $update_time ) { wc_set_user_last_update_time( $user_id ); } } add_action( 'update_user_meta', 'wc_meta_update_last_update_time', 10, 4 ); /** * Sets a user's "last update" time to the current timestamp. * * @since 2.6.0 * @param int $user_id The user to set a timestamp for. */ function wc_set_user_last_update_time( $user_id ) { update_user_meta( $user_id, 'last_update', gmdate( 'U' ) ); } /** * Get customer saved payment methods list. * * @since 2.6.0 * @param int $customer_id Customer ID. * @return array */ function wc_get_customer_saved_methods_list( $customer_id ) { return apply_filters( 'woocommerce_saved_payment_methods_list', array(), $customer_id ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment } /** * Get info about customer's last order. * * @since 2.6.0 * @param int $customer_id Customer ID. * @return WC_Order|bool Order object if successful or false. */ function wc_get_customer_last_order( $customer_id ) { $customer = new WC_Customer( $customer_id ); return $customer->get_last_order(); } /** * When a user is deleted in WordPress, delete corresponding WooCommerce data. * * @param int $user_id User ID being deleted. */ function wc_delete_user_data( $user_id ) { global $wpdb; // Clean up sessions. $wpdb->delete( $wpdb->prefix . 'woocommerce_sessions', array( 'session_key' => $user_id, ) ); // Revoke API keys. $wpdb->delete( $wpdb->prefix . 'woocommerce_api_keys', array( 'user_id' => $user_id, ) ); // Clean up payment tokens. $payment_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id ); foreach ( $payment_tokens as $payment_token ) { $payment_token->delete(); } } add_action( 'delete_user', 'wc_delete_user_data' ); /** * Store user agents. Used for tracker. * * @since 3.0.0 * @param string $user_login User login. * @param int|object $user User. */ function wc_maybe_store_user_agent( $user_login, $user ) { if ( 'yes' === get_option( 'woocommerce_allow_tracking', 'no' ) && user_can( $user, 'manage_woocommerce' ) ) { $admin_user_agents = array_filter( (array) get_option( 'woocommerce_tracker_ua', array() ) ); $admin_user_agents[] = wc_get_user_agent(); update_option( 'woocommerce_tracker_ua', array_unique( $admin_user_agents ), false ); } } add_action( 'wp_login', 'wc_maybe_store_user_agent', 10, 2 ); /** * Update logic triggered on login. * * @since 3.4.0 * @param string $user_login User login. * @param object $user User. */ function wc_user_logged_in( $user_login, $user ) { wc_update_user_last_active( $user->ID ); update_user_meta( $user->ID, '_woocommerce_load_saved_cart_after_login', 1 ); } add_action( 'wp_login', 'wc_user_logged_in', 10, 2 ); /** * Update when the user was last active. * * @since 3.4.0 */ function wc_current_user_is_active() { if ( ! is_user_logged_in() ) { return; } wc_update_user_last_active( get_current_user_id() ); } add_action( 'wp', 'wc_current_user_is_active', 10 ); /** * Set the user last active timestamp to now. * * @since 3.4.0 * @param int $user_id User ID to mark active. */ function wc_update_user_last_active( $user_id ) { if ( ! $user_id ) { return; } update_user_meta( $user_id, 'wc_last_active', (string) strtotime( gmdate( 'Y-m-d', time() ) ) ); } /** * Translate WC roles using the woocommerce textdomain. * * @since 3.7.0 * @param string $translation Translated text. * @param string $text Text to translate. * @param string $context Context information for the translators. * @param string $domain Text domain. Unique identifier for retrieving translated strings. * @return string */ function wc_translate_user_roles( $translation, $text, $context, $domain ) { // translate_user_role() only accepts a second parameter starting in WP 5.2. if ( version_compare( get_bloginfo( 'version' ), '5.2', '<' ) ) { return $translation; } if ( 'User role' === $context && 'default' === $domain && in_array( $text, array( 'Shop manager', 'Customer' ), true ) ) { return translate_user_role( $text, 'woocommerce' ); } return $translation; } add_filter( 'gettext_with_context', 'wc_translate_user_roles', 10, 4 ); 1xbet App Download Within Bangladesh For Google Android Apk & Ios 2024 - Ravian Technologies

Exclusive OFF Exclusive OFF - We are also offering one month free customer support after completing the project

AI Powered, Well Reputed and Trusted Company for Your Successful Business

1xbet App Download Within Bangladesh For Google Android Apk & Ios 2024

1xbet Software 1xbet Mobile ᐉ Download The 1xbet Apk Android & Iphone ᐉ 1-x-bet Com

You could email the assistance team to understand beginning your practice. Finding data around the 1xbet android os app before wagering on any celebration. If you need to check the particular stats of 2 teams that play, click the event.

If you possess iOS device, click on the button plus you’ll open mobile version of web site. Visit the company’s official website, which will allow you to download the document you need. Furthermore, you are suitable to claim the particular 100% match first deposit bonus of which is up in order to ৳130, 000 and even 150 free spins. The app is usually available, and an individual can access the app on virtually any device. This listing lists all kinds of esports that you can easily bet on inside the 1xBet APK app. Regardless regarding the bet end result, after it is usually settled, the consumer will receive a benefit as a free bet – 50% from the bet volume.

The Following Guide Describes The Steps You Need To Take To Create A 1xbet Account Upon Your Android Or Ios Device

The 1xbet program is obtainable on a variety associated with Android smart products. You can accessibility the program on Android TV Bins, tablets, and smart phone devices. The gaming interface of the particular mobile version facilitates portrait and panorama mode.

  • 1xBet Application in Bangladesh offers a comprehensive plus user-friendly platform with regard to sports betting in addition to casino gaming fans.
  • Players who already have a new 1xbet account usually are not required to register, as they can carry on logging in, generating financial transactions and even placing bets.
  • Many players just miss to allow typically the installation of software from unknown developers in their smartphone settings.
  • You can download in addition to install the 1xbet app just in a minute.
  • Players who would rather try their good fortune at betting upon casino games could connect to survive dealer platforms this kind of as Russian Different roulette games, 21, Wheel of Fortune and many other.
  • Players can easily play, deposit, and even do everything that they need to take pleasure in casino gaming via this apk software.

You’ll need a mobile phone device and Internet access to download the application you want. 1xBet Bangladesh is recognized as a prime sports betting site in the country and will be expected to supply the best quality inside its cricket markets. 1xBet App within BD related offers and offers become incentives to motivate more players and also a way for 1xBet to appreciate its clients. In this display we now have analysed the 1xBet cricket market in more detail. You may also search for improvements by going to the “My applications & games” area inside the Google Play Store or the particular “Updates” tab within the mobile iphone app. There is support provided” “with regard to users who possess no clue on just how to use 1xbet app 1xbet download.

Pros & Disadvantages Of Mobile Web Site For Bangladeshi Gamer:

The bookmaker has a state of the art technical team that will oversees the detailed functions of” “the website. Once you possess redeemed the signal, visit the site, locate the promo program code section and enter in your birthday promo code. Once this particular is done, you may immediately receive some sort of free bet assert message.

1Xbet will perform ideally even in case your mobile device is not up to date. To make mobile phone sports betting meet up with your expectations, follow responsible gaming rules. Besides studying figures, adhere to basic chance management rules.

X Bet App Live Match Broadcasting

It’s better to location small bets, 1%-5% of your total bankroll – this particular approach will assist always keep your chances associated with winning even following a series of losses. The 2025 version of 1xBet apk offers brand new users an increased welcome package like deposit bonuses and free bets. The introductory bonus composition provides multiple marketing options based on initial deposit amounts and preferred gambling activities. New customers can create wagering accounts directly throughout the mobile application having an accelerated registration procedure.

  • UX-friendly interface and simplest navigation makes typically the app ideal for starters and experienced customers.
  • After successfully downloading it the file, make sure you proceed to the installation phase.
  • In exchange betting, consumers can offer their very own own odds” “on the particular event as well as other users can pick to accept those probabilities and place a wager.
  • We believe it has answered concerns like “Is 1xbet a fantastic app?

After installing the 1xbet+apk on your device, the first thing you would might like to do is make your first bet. Not only the first-time downpayment, however you will always enjoy every action you want in order to take for typically the first time. On the underside dashboard, presently there are five icons where gamers can easily perform several wagering actions.

Common Problems With The 1xbet Apk Installation

The simply method to set up and download 1Xbet app is via the official website. The download is entirely free plus is processed via your phone. There is a special solution to take proper care of any technical issues, whether using the particular 1xbet latest apk or mobile web-site. When you encounter difficulties on the site, you can easily contact the assistance team to help you solve these people. Some channels on the webpage to help you connect to a representative include email, telephone number, live chat, etc. You can select single or multiple events depending on the choice.

Once you have effectively downloaded the mobile version of 1xbet, you can keep on betting and create transactions from your account. Experience unrivaled convenience and total access to most 1xBet features together with the mobile app optimized for Android in addition to iOS. No more browser delays or limited functionality—just natural, fast, and reliable betting at your current fingertips. Many individuals ask, “But why do I require an app in the event that I could merely bet on the internet? It’s a valid problem to ask, and even to answer of which question; we’d just like to show an individual a summary of typically the mobile version plus the 1Xbet mobile application. After this particular, the only issue left to perform will be log in for your requirements and continue placing bets.

Place Bets For The 1xbet Mobile App

This will give you exactly the same expertise as using” “typically the mobile app on your desktop. Launch settings from the mobile and ensure to modify your app sources. Most devices have auto-rejection regarding apps from unfamiliar places.

The 1xbet mobile app features an user-friendly graphical user interface for participants. When using the particular mobile app, players can easily engage in live sports gambling events, receive bonus deals and promotions, play casino games, anticipate soccer matches, in addition to much more. Live streaming support is surely an added advantage, as users can the actual events they have got predicted in advance. In the field of on the internet betting, 1xBet App stands out as one of the leading apps providing a wide variety of sports plus casino betting alternatives. Available for the two Android and iOS users, this application provides convenient use of a wide variety of sports events, casino games, along with live streaming and even live betting.

How Can I Obtain 1xbet?

The mobile betting computer software leverages advanced technology to make certain optimal functionality. It features a lightweight installation bundle that requires minimal storage space when providing direct entry to account management and banking capabilities. Built-in tools intended for analyzing sports stats enhance strategic decision-making, while the live stream capability for selected events keeps users engaged in actual time.

  • If you include iOS device, simply click the button plus you’ll open cell phone version of web site.
  • Common installation difficulties include insufficient storage place, incompatible Android editions, or security setting conflicts.
  • 1xBet Bangladesh is the leading sports betting web site in the nation and is definitely expected to supply the best quality within its cricket marketplaces.
  • “1xBet is one of the most well-liked online betting systems, offering a extensive range of benefits for users.
  • PCs great gadgets for conducting your current betting transactions, even so, betting by using an Google android device gives you the flexibility to employ the mobile edition of 1xbet anywhere you might be.

It is possible in order to withdraw rupees or perhaps foreign exchange or cryptocurrencies via bank playing cards or digital wallets, crypto wallets, cash, and electronic payment methods. It’s quick and straightforward to put your bets inside the 1Xbet casino. You’ll need to research and select your recommended game, then click it, and enter into your bet quantity.

How Must I Download And Mount The 1xbet Application On Android?

Some gamers become 1xbet users by enrolling via the cellular option. However, typically the 1xbet mobile application allows you to sign up in addition to fill in the particular promo code to be able to qualify for any encouraged bonus of” “around 130%. Summarily, you are able to get the apk when you visit typically the site. With any kind of new apk type, you will always enjoy the ideal online betting adventure on the site. We believe it includes answered concerns like “Is 1xbet a good app?

  • Additionally, 1xBet is known intended for offering competitive chances and various additional bonuses for new in addition to existing users.
  • You can access the program about Android TV Packing containers, tablets, and smartphone devices.
  • It’s important to be able to keep your app updated as new types often include pest fixes and efficiency improvements.
  • An amazing notification feature run by the 1xbet betting app permits it to notify users of actions alongside live activities.
  • Each time you log in, some sort of temporary password will certainly be sent to be able to an exclusive app, electronic mail, or SMS.

If you are utilized to placing wagers on the 1xbet online betting program on your computer system, you may desire to” “download and install the 1xbet mobile phone app for Android and iOS smartphones. This is exactly why we’ve gathered a great impressive team of developers to produce typically the most effective wagering application available within Bangladesh for mobile cricket betting or casino games. You can download the particular most recent edition in the 1Xbet cell phone app in Bangladesh. You’ll enjoy fantastic welcome bonus offers, the variety of mobile phone payments, an eye-catching design style, in addition to the flow involving work.

Is Typically The 1xbet Mobile App Safe In Bangladesh?

Common installation problems include insufficient space for storage, incompatible Android versions, or security setting conflicts. Regular revisions introduce performance improvements and new characteristics while maintaining backwards abiliyy. The software consists of built-in security steps protecting user information and financial dealings. You can down load 1xbet APK immediately from the internet site, making it easy to install in your system and start bets right away. OnexBit frequently upgrades it is software to repair bugs in the mobile phone apps, to stop the app from a crash.

  • Also, check that the Armenia area is selected throughout the market settings.
  • It contains the hotline quantity, email address, and details for communication via WhatsApp and even Telegram.
  • This welcome package involves up to a 100% bonus, getting up to 150, 000 BDT.
  • The player can predict any of the live matches involving your favorite athletics team or the player can forecast before any online sports match.
  • The best approach to protect your account is by enabling two-factor authentication.

Moreover, you are going to receive 150 free spins along with the welcome bonus. Lastly, there is typically the menu option that will has everything pointed out earlier. Under the particular menu option, a person can access the profile messages, deposit or withdraw, accessibility your account equilibrium, and even carry out special settings.

How To Set Up 1xbet Apk

To access the statistics section, choose an event from the lineup and faucet the “Statistics” button. The speed and even limits” “intended for deposits and cashouts depend on typically the chosen payment system. Before you are able to stimulate the welcome bonus, a person must have produced a deposit. Upon completing your initial deposit, your pleasant bonus will become transferred to your added bonus account. Try removing cache, restarting the particular app, or resetting your password.

  • This flexibility permits users from numerous regions to use the payment procedures they may be most comfortable with.
  • Finding data within the 1xbet google android app before bets on any occasion.
  • Please proceed in order to the App Retail outlet to start your current free download and unit installation of the 1xbet app.
  • Furthermore, you are entitled to claim typically the 100% match preliminary deposit bonus that is up to be able to ৳130, 000  plus 150 free spins.
  • To avoid any problems, also have the 1xbet apk download latest version.

Additionally, it’s complemented with 150 Free Spins, perfect for exploring the variety of slot games available about the app. When you make your 1st deposit for the 1xBet app, it includes an enticing incentive. Receive a 100% bonus on your initial deposit, with the potential to obtain up to fifteen, 600 BDT. This bonus effectively increases your betting power, allowing you to explore a new wider range regarding sports betting choices and increase your chances of winnining. The 1xBet app doesn’t just cater in order to sports betting fans. It’s important to maintain your app updated as new types often include irritate fixes and overall performance improvements.

What Is Missing By 1xbet App Throughout Bangladesh?

They have the privacy policy in place to ensure that user’s personal information is protected. The live bet match up broadcast for the 1xbet login app get brings you every one of the statistics from globally. Moreover, the 1xbet apk promo signal can help a person claim a delicious welcome bonus involving 100% matched bonus up to €1, 296/$1, 440 any time you choose your very first deposit. If an individual miss betting about any pre-match function, there is nothing to consider, as a person can still decide on your preferred market choices on the live game. You can access are living events as they perform from the are living section category. The first thing to do to create your current first bet within the apk is to fund your account with the minimum amount.

  • With its large range of bets options, live betting and streaming characteristics, and multilingual help, it caters effectively to the diverse needs of its users.
  • For users who else downloaded 1xBet to be able to Android, they want to periodically revise the APK data.
  • Please ensure that apps from unidentified sources can become installed on your device.
  • So, you will be an active player and eager in order to get the 1xbet mobile version upon your smartphone, make sure you be aware of which you cannot down load 1xbet apk by Google play.

You can” “also connect with the customer support staff under this tab. To enjoy betting in Live setting and achieve long-term success, download 1xBet to your smartphone and choose 1 from the suggested strategies. With the established app, players zero longer need in order to search for how in order to download the 1xBet mirror. It’s a lot safer and simpler to install typically the multifunctional software immediately. After downloading the particular installation package, locate it in the device’s Downloads file or notification -panel. Tap the data file to begin with installation, review the requested permissions which include access in order to storage and internet connectivity, then verify to complete the particular setup process.

How To Download The Particular 1xbet Mobile Application On Your Own Ios Device

With the 1xBet mobi app, you find speed, security, in addition to exclusive benefits unrivaled by every other system in Azerbaijan. Download now, use skilled tips, and revel in the particular full thrill regarding online betting in addition to casino gaming — anytime, anywhere. This welcome package contains up to some sort of 100% bonus, attaining up to one hundred fifty, 000 BDT.

  • This bonus consists involving a 100% on line casino and sports bets bonus.
  • The apk gives several thrilling on line casino titles across games for example slots, tables, and more.
  • Don’t skip push notifications with details about 1xbet app newest version.

” Considering the pros associated with the APK, an individual can see of which the app will certainly provide all the gambling needs. To avoid any issues, will have the 1xbet apk download newest version. Solutions include been implemented to help users sort 1xbet apk that doesn’t work. Failure to update the apk at times could be in charge of this kind of problem. On one other hand, you may well consider the next remedy if you obtain 1xbet apk with regard to android, but it doesn’t work. Virtual sports betting on 1 xbet apps allows users to gamble on sports clubs.

What Are The Essential Differences Between Making Use Of The 1xbet App And The Cell Phone Website?”

Get ready to check out the important points about getting and installing this particular mobile betting option. Make sure to hand over the particular bonus balance with accumulator bets five times, by selecting a few events or increased. Cumulative bets need to have odds of 1. 40 (2/5) or even a higher odd value. The 1xBet app allows large numbers of players by around the entire world place quick gambling bets on sports by anywhere on the particular planet! Yes, its indeed true that the 1Xbet app will be acceptable for employ in Bangladesh. Anyone can download it for complimentary in addition to earn real money along with bets.

  • On their phone, users can set up notifications regarding important sports occasions and watch are living broadcasts of exciting matches.
  • Players can accessibility pre-match and live betting markets, various casino games,” “plus exclusive mobile bonuses through a one consolidated application.
  • 1xBet Bangladesh is a internet gambling company that offers sports betting and casino games.
  • Downloading APK files from unknown resources is risky mainly because you might set up a fake type.

The quick registration system incorporates automated data validation to ensure accuracy whilst minimizing manual type requirements. Users could upgrade to total accounts at any time by simply providing additional verification documents through the application’s secure upload system. If an individual perform all typically the actions we pointed out above, you can conclude that 1xbet betting company provides a solid operational foundation.

You Can Customize The 1хbet Mobile App And So It’s Perfect For You

Alternatively, you may play with the bonus received in your account. This issue occurs intended for registered users which played on typically the official website in addition to then made a decision to obtain 1xBet for their smart phone but were unable in order to log in. To access their consideration, they need in order to click the “Forgot Password” button and choose one” “with the available options to restore access. A temporary password can be sent to be able to the user, who can enter it in the corresponding field and after that set a permanent one. The recognized website of the betting platform doesn’t send notifications about score changes, which in turn is a clear drawback for Survive betting fans.

  • After installing the 1xbet+apk on your system, the first thing you would need to do is make your current first bet.
  • When you launch the app, the homepage has a broad range of widgets where you can perform each betting action.
  • You can access reside events as they perform from the live section category.
  • The company even offers a mobile version of their website plus a mobile phone app that could be down loaded for both iOS and Android devices.
  • There is a “popular” tab of which showcases all accessible events on the particular site.

The iOS version of the application updates automatically – users don’t require any additional actions. For users that downloaded 1xBet in order to Android, they will need to periodically revise the APK data files. This can end up being done manually by visiting the bookmaker’s official website and just reinstalling the application. Alternatively, users can wait until the software automatically prompts them to mount new APK files.

Replies To “1xbet Apk”

Navigating down the site will also help gamers find activities like casinos as well as other games. All consumers who have down loaded the 1xBet iphone app have access to competent assistance. The quickest way to contact a supervisor is from the live chat. To begin a conversation with a specialist, click upon the online image. Alternative communication choices can be located in the “Contacts” section. It includes the hotline amount, email address, and details for communication via WhatsApp in addition to Telegram.

  • Its flexibility to local tastes, including language plus payment options, highlights its commitment in order to offering a personalized and accessible betting knowledge.
  • The features are similar to the primary site, so this specific is an benefits for loyal 1xbet participants.
  • Another reason to download the particular 1хBet app about your mobile will be the option of customizing it thus it’s just correct for you.
  • Registration rewards include the two sports betting and online casino gaming incentives, using separate bonus buildings for each and every category.

1xBet Bangladesh is a gambling online company that offers gambling and online casino games. The organization also has a cellular version of their own website plus a mobile app that could be downloaded for both iOS and Android products. The mobile app stands out for its intuitive interface, considerable betting options, in addition to reliable operation across different Android variations. Players can accessibility pre-match and reside betting markets, different casino games,” “and even exclusive mobile bonuses through a one consolidated application.

Scroll to Top
Scroll to Top
small_c_popup.png

Let's have a chat

Get A Quote