File "CreateAccount.php"
Full Path: /home/vantageo/public_html/cache/cache/cache/.wp-cli/wp-content/plugins/woocommerce/packages/woocommerce-blocks/src/Domain/Services/CreateAccount.php
File size: 8.5 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace Automattic\WooCommerce\Blocks\Domain\Services;
use \WP_REST_Request;
use \WC_Order;
use Automattic\WooCommerce\Blocks\Domain\Package;
use Automattic\WooCommerce\Blocks\Domain\Services\Email\CustomerNewAccount;
/**
* Service class implementing new create account behaviour for order processing.
*/
class CreateAccount {
/**
* Reference to the Package instance
*
* @var Package
*/
private $package;
/**
* Constructor.
*
* @param Package $package An instance of (Woo Blocks) Package.
*/
public function __construct( Package $package ) {
$this->package = $package;
}
/**
* Single method for feature gating logic. Used to gate all non-private methods.
*
* @return True if Checkout sign-up feature should be made available.
*/
private function is_feature_enabled() {
// Checkout signup is feature gated to WooCommerce 4.7 and newer;
// uses updated my-account/lost-password screen from 4.7+ for
// setting initial password.
// This service is feature gated to plugin only, to match the
// availability of the Checkout block (feature plugin only).
return $this->package->feature()->is_feature_plugin_build() && defined( 'WC_VERSION' ) && version_compare( WC_VERSION, '4.7', '>=' );
}
/**
* Init - register handlers for WooCommerce core email hooks.
*/
public function init() {
if ( ! self::is_feature_enabled() ) {
return;
}
// Override core email handlers to add our new improved "new account" email.
add_action(
'woocommerce_email',
function ( $wc_emails_instance ) {
// Remove core "new account" handler; we are going to replace it.
remove_action( 'woocommerce_created_customer_notification', array( $wc_emails_instance, 'customer_new_account' ), 10, 3 );
// Add custom "new account" handler.
add_action(
'woocommerce_created_customer_notification',
function( $customer_id, $new_customer_data = array(), $password_generated = false ) use ( $wc_emails_instance ) {
// If this is a block-based signup, send a new email
// with password reset link (no password in email).
if ( isset( $new_customer_data['is_checkout_block_customer_signup'] ) ) {
$this->customer_new_account( $customer_id, $new_customer_data );
return;
}
// Otherwise, trigger the existing legacy email (with new password inline).
$wc_emails_instance->customer_new_account( $customer_id, $new_customer_data, $password_generated );
},
10,
3
);
}
);
}
/**
* Trigger new account email.
* This is intended as a replacement to WC_Emails::customer_new_account(),
* with a set password link instead of emailing the new password in email
* content.
*
* @param int $customer_id The ID of the new customer account.
* @param array $new_customer_data Assoc array of data for the new account.
*/
public function customer_new_account( $customer_id = 0, array $new_customer_data = array() ) {
if ( ! self::is_feature_enabled() ) {
return;
}
if ( ! $customer_id ) {
return;
}
$new_account_email = new CustomerNewAccount( $this->package );
$new_account_email->trigger( $customer_id, $new_customer_data );
}
/**
* Create a user account for specified request (if necessary).
* If a new account is created:
* - The user is logged in.
*
* @param \WP_REST_Request $request The current request object being handled.
*
* @throws Exception On error.
* @return int The new user id, or 0 if no user was created.
*/
public function from_order_request( \WP_REST_Request $request ) {
if ( ! self::is_feature_enabled() || ! $this->should_create_customer_account( $request ) ) {
return 0;
}
$customer_id = $this->create_customer_account(
$request['billing_address']['email'],
$request['billing_address']['first_name'],
$request['billing_address']['last_name']
);
// Log the customer in and associate with the order.
wc_set_customer_auth_cookie( $customer_id );
return $customer_id;
}
/**
* Check request options and store (shop) config to determine if a user account
* should be created as part of order processing.
*
* @param \WP_REST_Request $request The current request object being handled.
*
* @return boolean True if a new user account should be created.
*/
protected function should_create_customer_account( \WP_REST_Request $request ) {
if ( is_user_logged_in() ) {
// User is already logged in - no need to create an account.
return false;
}
// From here we know that the shopper is not logged in.
// check for whether account creation is enabled at the global level.
$checkout = WC()->checkout();
if ( ! $checkout instanceof \WC_Checkout ) {
// If checkout class is not available, we have major problems, don't create account.
return false;
}
if ( false === filter_var( $checkout->is_registration_enabled(), FILTER_VALIDATE_BOOLEAN ) ) {
// Registration is not enabled for the store, so return false.
return false;
}
if ( true === filter_var( $checkout->is_registration_required(), FILTER_VALIDATE_BOOLEAN ) ) {
// Store requires an account for all checkouts (purchases).
// Create an account independent of shopper option in $request.
// Note - checkbox is not displayed to shopper in this case.
return true;
}
// From here we know that the store allows guest checkout;
// shopper can choose whether they sign up (`should_create_account`).
if ( true === filter_var( $request['should_create_account'], FILTER_VALIDATE_BOOLEAN ) ) {
// User has requested an account as part of checkout processing.
return true;
}
return false;
}
/**
* Convert an account creation error to an exception.
*
* @param \WP_Error $error An error object.
*
* @return Exception.
*/
private function map_create_account_error( \WP_Error $error ) {
switch ( $error->get_error_code() ) {
// WordPress core error codes.
case 'empty_username':
case 'invalid_username':
case 'empty_email':
case 'invalid_email':
case 'email_exists':
case 'registerfail':
return new \Exception( 'woocommerce_rest_checkout_create_account_failure' );
}
return new \Exception( 'woocommerce_rest_checkout_create_account_failure' );
}
/**
* Create a new account for a customer (using a new blocks-specific PHP API).
*
* The account is created with a generated username. The customer is sent
* an email notifying them about the account and containing a link to set
* their (initial) password.
*
* Intended as a replacement for wc_create_new_customer in WC core.
*
* @throws \Exception If an error is encountered when creating the user account.
*
* @param string $user_email The email address to use for the new account.
* @param string $first_name The first name to use for the new account.
* @param string $last_name The last name to use for the new account.
*
* @return int User id if successful
*/
private function create_customer_account( $user_email, $first_name, $last_name ) {
if ( empty( $user_email ) || ! is_email( $user_email ) ) {
throw new \Exception( 'registration-error-invalid-email' );
}
if ( email_exists( $user_email ) ) {
throw new \Exception( 'registration-error-email-exists' );
}
$username = wc_create_new_customer_username( $user_email );
// Handle password creation.
$password = wp_generate_password();
$password_generated = true;
// Use WP_Error to handle registration errors.
$errors = new \WP_Error();
do_action( 'woocommerce_register_post', $username, $user_email, $errors );
$errors = apply_filters( 'woocommerce_registration_errors', $errors, $username, $user_email );
if ( $errors->get_error_code() ) {
throw new \Exception( $errors->get_error_code() );
}
$new_customer_data = apply_filters(
'woocommerce_new_customer_data',
array(
'is_checkout_block_customer_signup' => true,
'user_login' => $username,
'user_pass' => $password,
'user_email' => $user_email,
'first_name' => $first_name,
'last_name' => $last_name,
'role' => 'customer',
)
);
$customer_id = wp_insert_user( $new_customer_data );
if ( is_wp_error( $customer_id ) ) {
throw $this->map_create_account_error( $customer_id );
}
// Set account flag to remind customer to update generated password.
update_user_option( $customer_id, 'default_password_nag', true, true );
do_action( 'woocommerce_created_customer', $customer_id, $new_customer_data, $password_generated );
return $customer_id;
}
}