Delayed account creation: Admin settings (#51236)

* Settings first pass

* New Settings UI

* Respect woocommerce_enable_delayed_account_creation at block level

* Add changefile(s) from automation for the following project(s): woocommerce-blocks, woocommerce

* Check input exists

* Add new setting to tests

---------

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Mike Jolley 2024-09-20 16:20:09 +01:00 committed by GitHub
parent 1ff28fd174
commit aacae66eb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 154 additions and 30 deletions

View File

@ -10,6 +10,7 @@ import {
useBlockProps, useBlockProps,
InspectorControls, InspectorControls,
} from '@wordpress/block-editor'; } from '@wordpress/block-editor';
import { getSetting } from '@woocommerce/settings';
/** /**
* Internal dependencies * Internal dependencies
@ -71,13 +72,18 @@ type EditProps = {
export const Edit = ( { export const Edit = ( {
attributes, attributes,
setAttributes, setAttributes,
}: EditProps ): JSX.Element => { }: EditProps ): JSX.Element | null => {
const className = clsx( 'wc-block-order-confirmation-create-account', { const className = clsx( 'wc-block-order-confirmation-create-account', {
'has-dark-controls': attributes.hasDarkControls, 'has-dark-controls': attributes.hasDarkControls,
} ); } );
const blockProps = useBlockProps( { const blockProps = useBlockProps( {
className, className,
} ); } );
const isEnabled = getSetting( 'delayedAccountCreationEnabled', true );
if ( ! isEnabled ) {
return null;
}
return ( return (
<div { ...blockProps }> <div { ...blockProps }>

View File

@ -0,0 +1,4 @@
Significance: patch
Type: tweak
Comment: Updates account creation options.

View File

@ -5190,8 +5190,38 @@ img.help_tip {
float: none; float: none;
} }
td.disabled { label:has(input:disabled) {
opacity: 0.5; cursor: not-allowed;
> input:disabled {
opacity: 0.7;
cursor: not-allowed;
pointer-events: none;
}
&[disabled-tooltip] {
position: relative;
}
&[disabled-tooltip]::before {
pointer-events: none;
content: attr(disabled-tooltip);
position: absolute;
top: -6px;
left: 6px;
transform: translateX(-50%) translateY(-100%);
background: black;
text-align: center;
color: #fff;
padding: 6px;
font-size: 12px;
min-width: 80px;
max-width: 200px;
border-radius: 5px;
pointer-events: none;
opacity:0;
}
&[disabled-tooltip]:hover::before,
&[disabled-tooltip]:focus::before {
opacity:1
}
} }
fieldset { fieldset {

View File

@ -12,6 +12,7 @@ if ( class_exists( 'WC_Settings_Accounts', false ) ) {
} }
use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils; use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;
use Automattic\WooCommerce\Admin\Features\Features;
/** /**
* WC_Settings_Accounts. * WC_Settings_Accounts.
@ -78,9 +79,27 @@ class WC_Settings_Accounts extends WC_Settings_Page {
'default' => 'no', 'default' => 'no',
'type' => 'checkbox', 'type' => 'checkbox',
'checkboxgroup' => 'start', 'checkboxgroup' => 'start',
'legend' => __( 'Allow customers to create an account:', 'woocommerce' ), 'legend' => __( 'Allow customers to create an account', 'woocommerce' ),
'autoload' => false, 'autoload' => false,
), ),
array(
'title' => __( 'Account creation', 'woocommerce' ),
'desc' => __( 'After checkout (recommended)', 'woocommerce' ),
'desc_tip' => sprintf(
/* Translators: %1$s and %2$s are opening and closing <a> tags respectively. */
__( 'Customers can create an account after their order is placed. Customize messaging %1$shere%2$s.', 'woocommerce' ),
'<a href="' . esc_url( admin_url( 'site-editor.php?postId=woocommerce%2Fwoocommerce%2F%2Forder-confirmation&postType=wp_template&canvas=edit' ) ) . '">',
'</a>'
),
'id' => 'woocommerce_enable_delayed_account_creation',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => '',
'autoload' => false,
'custom_attributes' => array(
'disabled-tooltip' => __( 'Enable guest checkout to use this feature.', 'woocommerce' ),
),
),
array( array(
'title' => __( 'Account creation', 'woocommerce' ), 'title' => __( 'Account creation', 'woocommerce' ),
'desc' => __( 'On "My account" page', 'woocommerce' ), 'desc' => __( 'On "My account" page', 'woocommerce' ),
@ -91,24 +110,30 @@ class WC_Settings_Accounts extends WC_Settings_Page {
'autoload' => false, 'autoload' => false,
), ),
array( array(
'title' => __( 'Account creation options', 'woocommerce' ), 'title' => __( 'Account creation options', 'woocommerce' ),
'desc' => __( 'Use email address as account login (recommended)', 'woocommerce' ), 'desc' => __( 'Send password setup link (recommended)', 'woocommerce' ),
'desc_tip' => __( 'If unchecked, customers will need to set a username during account creation.', 'woocommerce' ), 'desc_tip' => __( 'New users receive an email to set up their password.', 'woocommerce' ),
'id' => 'woocommerce_registration_generate_username', 'id' => 'woocommerce_registration_generate_password',
'default' => 'yes', 'default' => 'yes',
'type' => 'checkbox', 'type' => 'checkbox',
'checkboxgroup' => 'start', 'checkboxgroup' => 'start',
'autoload' => false, 'autoload' => false,
'custom_attributes' => array(
'disabled-tooltip' => __( 'Enable an account creation method to use this feature.', 'woocommerce' ),
),
), ),
array( array(
'title' => __( 'Account creation options', 'woocommerce' ), 'title' => __( 'Account creation options', 'woocommerce' ),
'desc' => __( 'Send password setup link (recommended)', 'woocommerce' ), 'desc' => __( 'Use email address as account login (recommended)', 'woocommerce' ),
'desc_tip' => __( 'New customers receive an email to set up their password.', 'woocommerce' ), 'desc_tip' => __( 'If unchecked, customers will need to set a username during account creation.', 'woocommerce' ),
'id' => 'woocommerce_registration_generate_password', 'id' => 'woocommerce_registration_generate_username',
'default' => 'yes', 'default' => 'yes',
'type' => 'checkbox', 'type' => 'checkbox',
'checkboxgroup' => 'end', 'checkboxgroup' => 'end',
'autoload' => false, 'autoload' => false,
'custom_attributes' => array(
'disabled-tooltip' => __( 'Enable an account creation method to use this feature.', 'woocommerce' ),
),
), ),
array( array(
'title' => __( 'Account erasure requests', 'woocommerce' ), 'title' => __( 'Account erasure requests', 'woocommerce' ),
@ -239,6 +264,15 @@ class WC_Settings_Accounts extends WC_Settings_Page {
), ),
); );
if ( ! Features::is_enabled( 'experimental-blocks' ) ) {
$account_settings = array_filter(
$account_settings,
function ( $setting ) {
return 'woocommerce_enable_delayed_account_creation' !== $setting['id'];
},
);
}
// Change settings when using the block based checkout. // Change settings when using the block based checkout.
if ( CartCheckoutUtils::is_checkout_block_default() ) { if ( CartCheckoutUtils::is_checkout_block_default() ) {
$account_settings = array_filter( $account_settings = array_filter(
@ -256,6 +290,24 @@ class WC_Settings_Accounts extends WC_Settings_Page {
}, },
$account_settings $account_settings
); );
} else {
$account_settings = array_map(
function ( $setting ) {
if ( 'woocommerce_enable_delayed_account_creation' === $setting['id'] ) {
$setting['desc_tip'] = sprintf(
/* Translators: %1$s and %2$s are opening and closing <a> tags respectively. */
__( 'This feature is only available with the Cart & Checkout blocks. %1$sLearn more%2$s.', 'woocommerce' ),
'<a href="https://woocommerce.com/document/woocommerce-store-editing/customizing-cart-and-checkout">',
'</a>'
);
$setting['disabled'] = true;
$setting['value'] = 0;
$setting['custom_attributes']['disabled-tooltip'] = __( 'Your store is using shortcode checkout. Use the Checkout blocks to activate this option.', 'woocommerce' );
}
return $setting;
},
$account_settings
);
} }
/** /**
@ -278,29 +330,49 @@ class WC_Settings_Accounts extends WC_Settings_Page {
?> ?>
<script type="text/javascript"> <script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Move tooltips to label element. This is not possible through the settings field API so this is a workaround
// until said API is refactored.
document.querySelectorAll('input[disabled-tooltip]').forEach(function(element) {
const label = element.closest('label');
label.setAttribute('disabled-tooltip', element.getAttribute('disabled-tooltip'));
});
// This handles settings that are enabled/disabled based on other settings.
const checkboxes = [ const checkboxes = [
document.getElementById("woocommerce_enable_signup_and_login_from_checkout"), document.getElementById("woocommerce_enable_signup_and_login_from_checkout"),
document.getElementById("woocommerce_enable_myaccount_registration"), document.getElementById("woocommerce_enable_myaccount_registration"),
document.getElementById("woocommerce_enable_delayed_account_creation"),
document.getElementById("woocommerce_enable_signup_from_checkout_for_subscriptions") document.getElementById("woocommerce_enable_signup_from_checkout_for_subscriptions")
]; ];
const inputs = [ const inputs = [
document.getElementById("woocommerce_registration_generate_username"), document.getElementById("woocommerce_registration_generate_username"),
document.getElementById("woocommerce_registration_generate_password") document.getElementById("woocommerce_registration_generate_password")
]; ];
checkboxes.forEach(cb => cb && cb.addEventListener('change', function() {
function updateInputs() {
const isChecked = checkboxes.some(cb => cb && cb.checked); const isChecked = checkboxes.some(cb => cb && cb.checked);
inputs.forEach(input => { inputs.forEach(input => {
if ( ! input ) { if ( ! input ) {
return; return;
} }
input.disabled = !isChecked; input.disabled = !isChecked;
input.closest('td').classList.toggle("disabled", !isChecked);
}); });
} }));
checkboxes[0].dispatchEvent(new Event('change')); // Initial state
checkboxes.forEach(cb => cb && cb.addEventListener('change', updateInputs)); // Guest checkout should toggle off some options.
updateInputs(); // Initial state const guestCheckout = document.getElementById("woocommerce_enable_guest_checkout");
if ( guestCheckout ) {
guestCheckout.addEventListener('change', function() {
const isChecked = this.checked;
const input = document.getElementById("woocommerce_enable_delayed_account_creation");
if ( ! input ) {
return;
}
input.disabled = !isChecked;
});
guestCheckout.dispatchEvent(new Event('change')); // Initial state
}
}); });
</script> </script>
<?php <?php

View File

@ -4,6 +4,7 @@ declare( strict_types = 1 );
namespace Automattic\WooCommerce\Blocks\BlockTypes\OrderConfirmation; namespace Automattic\WooCommerce\Blocks\BlockTypes\OrderConfirmation;
use Automattic\WooCommerce\StoreApi\Utilities\OrderController; use Automattic\WooCommerce\StoreApi\Utilities\OrderController;
use Automattic\WooCommerce\Admin\Features\Features;
/** /**
* CreateAccount class. * CreateAccount class.
@ -33,6 +34,15 @@ class CreateAccount extends AbstractOrderConfirmationBlock {
return $key ? $script[ $key ] : $script; return $key ? $script[ $key ] : $script;
} }
/**
* Returns if delayed account creation is enabled.
*
* @return bool
*/
protected function is_feature_enabled() {
return Features::is_enabled( 'experimental-blocks' ) && get_option( 'woocommerce_enable_delayed_account_creation', 'yes' ) === 'yes';
}
/** /**
* Process posted account form. * Process posted account form.
* *
@ -111,7 +121,7 @@ class CreateAccount extends AbstractOrderConfirmationBlock {
* @return string * @return string
*/ */
protected function render_content( $order, $permission = false, $attributes = [], $content = '' ) { protected function render_content( $order, $permission = false, $attributes = [], $content = '' ) {
if ( ! $permission ) { if ( ! $permission || ! $this->is_feature_enabled() ) {
return ''; return '';
} }
@ -189,6 +199,7 @@ class CreateAccount extends AbstractOrderConfirmationBlock {
protected function enqueue_data( array $attributes = [] ) { protected function enqueue_data( array $attributes = [] ) {
parent::enqueue_data( $attributes ); parent::enqueue_data( $attributes );
$this->asset_data_registry->add( 'delayedAccountCreationEnabled', $this->is_feature_enabled() );
$this->asset_data_registry->add( 'registrationGeneratePassword', filter_var( get_option( 'woocommerce_registration_generate_password' ), FILTER_VALIDATE_BOOLEAN ) ); $this->asset_data_registry->add( 'registrationGeneratePassword', filter_var( get_option( 'woocommerce_registration_generate_password' ), FILTER_VALIDATE_BOOLEAN ) );
} }
} }

View File

@ -22,7 +22,7 @@ class WC_Settings_Accounts_Test extends WC_Settings_Unit_Test_Case {
add_filter( add_filter(
'woocommerce_account_settings', 'woocommerce_account_settings',
function( $settings ) use ( &$actual_settings_via_filter ) { function ( $settings ) use ( &$actual_settings_via_filter ) {
$actual_settings_via_filter = $settings; $actual_settings_via_filter = $settings;
return $settings; return $settings;
}, },
@ -67,6 +67,7 @@ class WC_Settings_Accounts_Test extends WC_Settings_Unit_Test_Case {
'woocommerce_trash_failed_orders' => 'relative_date_selector', 'woocommerce_trash_failed_orders' => 'relative_date_selector',
'woocommerce_trash_cancelled_orders' => 'relative_date_selector', 'woocommerce_trash_cancelled_orders' => 'relative_date_selector',
'woocommerce_anonymize_completed_orders' => 'relative_date_selector', 'woocommerce_anonymize_completed_orders' => 'relative_date_selector',
'woocommerce_enable_delayed_account_creation' => 'checkbox',
); );
$this->assertEquals( $expected, $settings_ids_and_types ); $this->assertEquals( $expected, $settings_ids_and_types );
@ -113,12 +114,12 @@ class WC_Settings_Accounts_Test extends WC_Settings_Unit_Test_Case {
public function test_linked_text_for_erasure_request_settings( $current_user_can_manage_privacy_options, $blog_version, $expected_order_erasure_text, $expected_downloads_erasure_text ) { public function test_linked_text_for_erasure_request_settings( $current_user_can_manage_privacy_options, $blog_version, $expected_order_erasure_text, $expected_downloads_erasure_text ) {
FunctionsMockerHack::add_function_mocks( FunctionsMockerHack::add_function_mocks(
array( array(
'current_user_can' => function( $capability, ...$args ) use ( $current_user_can_manage_privacy_options ) { 'current_user_can' => function ( $capability, ...$args ) use ( $current_user_can_manage_privacy_options ) {
return 'manage_privacy_options' === $capability ? return 'manage_privacy_options' === $capability ?
$current_user_can_manage_privacy_options : $current_user_can_manage_privacy_options :
current_user_can( $capability, ...$args ); current_user_can( $capability, ...$args );
}, },
'get_bloginfo' => function( $show = '', $filter = 'raw' ) use ( $blog_version ) { 'get_bloginfo' => function ( $show = '', $filter = 'raw' ) use ( $blog_version ) {
return 'version' === $show ? return 'version' === $show ?
$blog_version : $blog_version :
get_bloginfo( $show, $filter ); get_bloginfo( $show, $filter );