[Experimental] Surface custom fields in My Account pages (#43823)
* Get default attributes on front end * Remove console log * Show notice about 0 registered fields in editor * Do not show block in editor if no fields are registered * Wrapper block * Update webpack config * Wrapper block type definition * Separate fields from the hook block * Hide when no custom fields exist * Address and contact fields * Shared form fields in settings * Revert render_content to original * Allow definition of unchecked value which includes a hidden field * Move woocommerce_edit_account_form above password section, which should be last. * My Account hooks * Move account handling to service class * Show fields in order details * Remove unused prop * remove comment * Hook docblocks * Add changefile(s) from automation for the following project(s): woocommerce * Add note about nonce verification * wp_kses_post for label * fix nonce linting * Add docblock to hook * Bump template version * Persist contact fields to customer * Change action name * Add changefile(s) from automation for the following project(s): woocommerce * Changelog * Margin fix on order confirmation for older core themes * Bump version tags --------- Co-authored-by: Thomas Roberts <thomas.roberts@automattic.com> Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
parent
877a16096c
commit
d858d22930
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: update
|
||||
|
||||
Introduced `woocommerce_my_account_after_my_address`, `woocommerce_order_details_after_customer_address`, and `woocommerce_edit_account_form_fields` hooks.
|
|
@ -1002,7 +1002,8 @@ ul.wc-tabs {
|
|||
}
|
||||
|
||||
.woocommerce-thankyou-order-received,
|
||||
h2.woocommerce-column__title {
|
||||
.woocommerce-column__title,
|
||||
.woocommerce-customer-details h2 {
|
||||
font-family: var(--wp--preset--font-family--source-serif-pro);
|
||||
}
|
||||
|
||||
|
|
|
@ -349,7 +349,8 @@ a.added_to_cart {
|
|||
* Order confirmation
|
||||
*/
|
||||
.woocommerce-thankyou-order-received,
|
||||
h2.woocommerce-column__title {
|
||||
.woocommerce-column__title,
|
||||
.woocommerce-customer-details h2 {
|
||||
font-size: var(--wp--preset--font-size--large);
|
||||
font-weight: 300;
|
||||
}
|
||||
|
@ -383,7 +384,7 @@ a.added_to_cart {
|
|||
// Ensure customer details match order overview.
|
||||
box-sizing: border-box;
|
||||
width: 70%;
|
||||
padding: 2rem;
|
||||
padding: 1rem;
|
||||
border-width: 1px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
|
|
@ -1410,8 +1410,86 @@ p.demo_store,
|
|||
}
|
||||
}
|
||||
|
||||
.woocommerce-customer-details .addresses,
|
||||
.woocommerce-customer-details .additional-fields {
|
||||
margin-bottom: 2em;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.addresses .wc-block-components-additional-fields-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
dt {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
display: inline;
|
||||
|
||||
&::after {
|
||||
content: ": ";
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-style: normal;
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-order-confirmation-additional-fields-wrapper .wc-block-components-additional-fields-list {
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr max-content;
|
||||
|
||||
dt {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
margin: 0 !important;
|
||||
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
dd {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
text-align: right;
|
||||
margin: 0 !important;
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-customer-details {
|
||||
|
||||
.woocommerce-column__title {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
address {
|
||||
font-style: normal;
|
||||
margin-bottom: 0;
|
||||
|
@ -1422,12 +1500,16 @@ p.demo_store,
|
|||
width: 100%;
|
||||
border-radius: 5px;
|
||||
padding: 6px 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.woocommerce-customer-details--phone,
|
||||
.woocommerce-customer-details--email {
|
||||
margin-bottom: 0;
|
||||
padding-left: 1.5em;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-customer-details--phone::before {
|
||||
|
@ -1634,6 +1716,7 @@ p.demo_store,
|
|||
*/
|
||||
.woocommerce:where(body:not(.woocommerce-block-theme-has-button-styles)),
|
||||
:where(body:not(.woocommerce-block-theme-has-button-styles)) .woocommerce {
|
||||
|
||||
a.button,
|
||||
button.button,
|
||||
input.button,
|
||||
|
@ -1740,6 +1823,7 @@ p.demo_store,
|
|||
}
|
||||
|
||||
div.product {
|
||||
|
||||
span.price,
|
||||
p.price {
|
||||
color: $highlight;
|
||||
|
|
|
@ -2830,6 +2830,8 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
|
|||
'default' => '',
|
||||
'autofocus' => '',
|
||||
'priority' => '',
|
||||
'unchecked_value' => null,
|
||||
'checked_value' => '1',
|
||||
);
|
||||
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
@ -2956,8 +2958,24 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
|
|||
|
||||
break;
|
||||
case 'checkbox':
|
||||
$field = '<label class="checkbox ' . implode( ' ', $args['label_class'] ) . '" ' . implode( ' ', $custom_attributes ) . '>
|
||||
<input type="' . esc_attr( $args['type'] ) . '" class="input-checkbox ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" value="1" ' . checked( $value, 1, false ) . ' /> ' . $args['label'] . $required . '</label>';
|
||||
$field = '<label class="checkbox ' . esc_attr( implode( ' ', $args['label_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . '>';
|
||||
|
||||
// Output a hidden field so a value is POSTed if the box is not checked.
|
||||
if ( ! is_null( $args['unchecked_value'] ) ) {
|
||||
$field .= sprintf( '<input type="hidden" name="%1$s" value="%2$s" />', esc_attr( $key ), esc_attr( $args['unchecked_value'] ) );
|
||||
}
|
||||
|
||||
$field .= sprintf(
|
||||
'<input type="checkbox" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s /> %6$s',
|
||||
esc_attr( $key ),
|
||||
esc_attr( $args['id'] ),
|
||||
esc_attr( $args['checked_value'] ),
|
||||
esc_attr( 'input-checkbox ' . implode( ' ', $args['input_class'] ) ),
|
||||
checked( $value, $args['checked_value'], false ),
|
||||
wp_kses_post( $args['label'] )
|
||||
);
|
||||
|
||||
$field .= $required . '</label>';
|
||||
|
||||
break;
|
||||
case 'text':
|
||||
|
|
|
@ -16,6 +16,7 @@ use Automattic\WooCommerce\Blocks\Domain\Services\GoogleAnalytics;
|
|||
use Automattic\WooCommerce\Blocks\Domain\Services\Hydration;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFields;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFieldsAdmin;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFieldsFrontend;
|
||||
use Automattic\WooCommerce\Blocks\InboxNotifications;
|
||||
use Automattic\WooCommerce\Blocks\Installer;
|
||||
use Automattic\WooCommerce\Blocks\Migration;
|
||||
|
@ -142,7 +143,7 @@ class Bootstrap {
|
|||
$this->container->get( Installer::class )->init();
|
||||
$this->container->get( GoogleAnalytics::class )->init();
|
||||
$this->container->get( CheckoutFields::class )->init();
|
||||
$this->container->get( CheckoutFieldsAdmin::class )->init();
|
||||
$this->container->get( is_admin() ? CheckoutFieldsAdmin::class : CheckoutFieldsFrontend::class )->init();
|
||||
}
|
||||
|
||||
// Load assets unless this is a request specifically for the store API.
|
||||
|
@ -362,6 +363,13 @@ class Bootstrap {
|
|||
return new CheckoutFieldsAdmin( $checkout_fields_controller );
|
||||
}
|
||||
);
|
||||
$this->container->register(
|
||||
CheckoutFieldsFrontend::class,
|
||||
function( Container $container ) {
|
||||
$checkout_fields_controller = $container->get( CheckoutFields::class );
|
||||
return new CheckoutFieldsFrontend( $checkout_fields_controller );
|
||||
}
|
||||
);
|
||||
$this->container->register(
|
||||
PaymentsApi::class,
|
||||
function ( Container $container ) {
|
||||
|
|
|
@ -1001,7 +1001,10 @@ class CheckoutFields {
|
|||
* @return array The filtered fields.
|
||||
*/
|
||||
public function filter_fields_for_customer( $fields ) {
|
||||
$customer_fields_keys = $this->get_address_fields_keys();
|
||||
$customer_fields_keys = array_merge(
|
||||
$this->get_address_fields_keys(),
|
||||
$this->get_contact_fields_keys()
|
||||
);
|
||||
return array_filter(
|
||||
$fields,
|
||||
function( $key ) use ( $customer_fields_keys ) {
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Blocks\Domain\Services;
|
||||
|
||||
use WC_Customer;
|
||||
use WC_Order;
|
||||
|
||||
/**
|
||||
* Service class managing checkout fields and its related extensibility points on the frontend.
|
||||
*/
|
||||
class CheckoutFieldsFrontend {
|
||||
|
||||
/**
|
||||
* Checkout field controller.
|
||||
*
|
||||
* @var CheckoutFields
|
||||
*/
|
||||
private $checkout_fields_controller;
|
||||
|
||||
/**
|
||||
* Sets up core fields.
|
||||
*
|
||||
* @param CheckoutFields $checkout_fields_controller Instance of the checkout field controller.
|
||||
*/
|
||||
public function __construct( CheckoutFields $checkout_fields_controller ) {
|
||||
$this->checkout_fields_controller = $checkout_fields_controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize hooks. This is not run Store API requests.
|
||||
*/
|
||||
public function init() {
|
||||
// Show custom checkout fields on the order details page.
|
||||
add_action( 'woocommerce_order_details_after_customer_address', array( $this, 'render_order_address_fields' ), 10, 2 );
|
||||
add_action( 'woocommerce_order_details_after_customer_details', array( $this, 'render_order_additional_fields' ), 10 );
|
||||
|
||||
// Show custom checkout fields on the My Account page.
|
||||
add_action( 'woocommerce_my_account_after_my_address', array( $this, 'render_address_fields' ), 10, 1 );
|
||||
|
||||
// Field editing in my account area.
|
||||
add_filter( 'woocommerce_save_account_details_required_fields', array( $this, 'edit_account_form_required_fields' ), 10, 1 );
|
||||
add_filter( 'woocommerce_edit_account_form_fields', array( $this, 'edit_account_form_fields' ), 10, 1 );
|
||||
add_action( 'woocommerce_save_account_details', array( $this, 'save_account_form_fields' ), 10, 1 );
|
||||
add_filter( 'woocommerce_address_to_edit', array( $this, 'edit_address_fields' ), 10, 2 );
|
||||
add_action( 'woocommerce_after_save_address_validation', array( $this, 'save_address_fields' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render custom fields.
|
||||
*
|
||||
* @param array $fields List of additional fields with values.
|
||||
* @return string
|
||||
*/
|
||||
protected function render_additional_fields( $fields ) {
|
||||
return ! empty( $fields ) ? '<dl class="wc-block-components-additional-fields-list">' . implode( '', array_map( array( $this, 'render_additional_field' ), $fields ) ) . '</dl>' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render custom field.
|
||||
*
|
||||
* @param array $field An additional field and value.
|
||||
* @return string
|
||||
*/
|
||||
protected function render_additional_field( $field ) {
|
||||
return sprintf(
|
||||
'<dt>%1$s</dt><dd>%2$s</dd>',
|
||||
esc_html( $field['label'] ),
|
||||
esc_html( $field['value'] )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders address fields on the order details page.
|
||||
*
|
||||
* @param string $address_type Type of address (billing or shipping).
|
||||
* @param WC_Order $order Order object.
|
||||
*/
|
||||
public function render_order_address_fields( $address_type, $order ) {
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo $this->render_additional_fields( $this->checkout_fields_controller->get_order_additional_fields_with_values( $order, 'address', $address_type, 'view' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders additional fields on the order details page.
|
||||
*
|
||||
* @param WC_Order $order Order object.
|
||||
*/
|
||||
public function render_order_additional_fields( $order ) {
|
||||
$fields = array_merge(
|
||||
$this->checkout_fields_controller->get_order_additional_fields_with_values( $order, 'contact', '', 'view' ),
|
||||
$this->checkout_fields_controller->get_order_additional_fields_with_values( $order, 'additional', '', 'view' ),
|
||||
);
|
||||
|
||||
if ( ! $fields ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<section class="wc-block-order-confirmation-additional-fields-wrapper">';
|
||||
echo '<h2>' . esc_html__( 'Additional information', 'woocommerce' ) . '</h2>';
|
||||
echo $this->render_additional_fields( $fields ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders address fields on the account page.
|
||||
*
|
||||
* @param string $address_type Type of address (billing or shipping).
|
||||
*/
|
||||
public function render_address_fields( $address_type ) {
|
||||
if ( ! in_array( $address_type, array( 'billing', 'shipping' ), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$customer = new WC_Customer( get_current_user_id() );
|
||||
$fields = $this->checkout_fields_controller->get_fields_for_location( 'address' );
|
||||
|
||||
if ( ! $fields || ! $customer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $fields as $key => $field ) {
|
||||
$value = $this->checkout_fields_controller->format_additional_field_value(
|
||||
$this->checkout_fields_controller->get_field_from_customer( $key, $customer, $address_type ),
|
||||
$field
|
||||
);
|
||||
|
||||
if ( ! $value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf( '<br><strong>%s</strong>: %s', wp_kses_post( $field['label'] ), wp_kses_post( $value ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register required additional contact fields.
|
||||
*
|
||||
* @param array $fields Required fields.
|
||||
* @return array
|
||||
*/
|
||||
public function edit_account_form_required_fields( $fields ) {
|
||||
$additional_fields = $this->checkout_fields_controller->get_fields_for_location( 'contact' );
|
||||
|
||||
foreach ( $additional_fields as $key => $field ) {
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$fields[ $key ] = $field['label'];
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds additional contact fields to the My Account edit account form.
|
||||
*/
|
||||
public function edit_account_form_fields() {
|
||||
$customer = new WC_Customer( get_current_user_id() );
|
||||
$fields = $this->checkout_fields_controller->get_fields_for_location( 'contact' );
|
||||
|
||||
foreach ( $fields as $key => $field ) {
|
||||
$form_field = $field;
|
||||
$form_field['value'] = $this->checkout_fields_controller->get_field_from_customer( $key, $customer, 'contact' );
|
||||
|
||||
if ( 'select' === $field['type'] ) {
|
||||
$form_field['options'] = array_column( $field['options'], 'label', 'value' );
|
||||
}
|
||||
|
||||
if ( 'checkbox' === $field['type'] ) {
|
||||
$form_field['checked_value'] = '1';
|
||||
$form_field['unchecked_value'] = '0';
|
||||
}
|
||||
|
||||
woocommerce_form_field( $key, $form_field, wc_get_post_data_by_key( $key, $form_field['value'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and saves additional address fields to the customer object on the My Account page.
|
||||
*
|
||||
* @param integer $user_id User ID.
|
||||
*/
|
||||
public function save_account_form_fields( $user_id ) {
|
||||
$customer = new WC_Customer( $user_id );
|
||||
$fields = $this->checkout_fields_controller->get_fields_for_location( 'contact' );
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||||
foreach ( $fields as $field_key => $field ) {
|
||||
if ( ! isset( $_POST[ $field_key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
$this->checkout_fields_controller->persist_field_for_customer( $field_key, wc_clean( wp_unslash( $_POST[ $field_key ] ) ), $customer );
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds additional address fields to the My Account edit address form.
|
||||
*
|
||||
* @param array $address Address fields.
|
||||
* @param string $address_type Type of address (billing or shipping).
|
||||
* @return array Updated address fields.
|
||||
*/
|
||||
public function edit_address_fields( $address, $address_type ) {
|
||||
$customer = new WC_Customer( get_current_user_id() );
|
||||
$fields = $this->checkout_fields_controller->get_fields_for_location( 'address' );
|
||||
|
||||
foreach ( $fields as $key => $field ) {
|
||||
$field_key = 'billing' === $address_type ? '/billing/' . $key : '/shipping/' . $key;
|
||||
$address[ $field_key ] = $field;
|
||||
$address[ $field_key ]['value'] = $this->checkout_fields_controller->get_field_from_customer( $key, $customer, $address_type );
|
||||
|
||||
if ( 'select' === $field['type'] ) {
|
||||
$address[ $field_key ]['options'] = array_column( $field['options'], 'label', 'value' );
|
||||
}
|
||||
|
||||
if ( 'checkbox' === $field['type'] ) {
|
||||
$address[ $field_key ]['checked_value'] = '1';
|
||||
$address[ $field_key ]['unchecked_value'] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and saves additional address fields to the customer object on the My Account page.
|
||||
*
|
||||
* @param integer $user_id User ID.
|
||||
* @param string $address_type Type of address (billing or shipping).
|
||||
*/
|
||||
public function save_address_fields( $user_id, $address_type ) {
|
||||
$customer = new WC_Customer( $user_id );
|
||||
$fields = $this->checkout_fields_controller->get_fields_for_location( 'address' );
|
||||
|
||||
// Nonces are checked before the action is fired that this function hooks into.
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||||
foreach ( $fields as $key => $field ) {
|
||||
$field_key = 'billing' === $address_type ? '/billing/' . $key : '/shipping/' . $key;
|
||||
|
||||
if ( ! isset( $_POST[ $field_key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = wc_clean( wp_unslash( $_POST[ $field_key ] ) );
|
||||
|
||||
if ( ! empty( $field['required'] ) && empty( $value ) ) {
|
||||
// translators: %s field label.
|
||||
wc_add_notice( sprintf( __( '%s is a required field.', 'woocommerce' ), $field['label'] ), 'error' );
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->checkout_fields_controller->persist_field_for_customer( $field_key, $value, $customer );
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* @see https://woo.com/document/template-structure/
|
||||
* @package WooCommerce\Templates
|
||||
* @version 7.0.1
|
||||
* @version 8.7.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
@ -44,6 +44,15 @@ do_action( 'woocommerce_before_edit_account_form' ); ?>
|
|||
<input type="email" class="woocommerce-Input woocommerce-Input--email input-text" name="account_email" id="account_email" autocomplete="email" value="<?php echo esc_attr( $user->user_email ); ?>" />
|
||||
</p>
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Hook where additional fields should be rendered.
|
||||
*
|
||||
* @since 8.7.0
|
||||
*/
|
||||
do_action( 'woocommerce_edit_account_form_fields' );
|
||||
?>
|
||||
|
||||
<fieldset>
|
||||
<legend><?php esc_html_e( 'Password change', 'woocommerce' ); ?></legend>
|
||||
|
||||
|
@ -62,7 +71,14 @@ do_action( 'woocommerce_before_edit_account_form' ); ?>
|
|||
</fieldset>
|
||||
<div class="clear"></div>
|
||||
|
||||
<?php do_action( 'woocommerce_edit_account_form' ); ?>
|
||||
<?php
|
||||
/**
|
||||
* My Account edit account form.
|
||||
*
|
||||
* @since 2.6.0
|
||||
*/
|
||||
do_action( 'woocommerce_edit_account_form' );
|
||||
?>
|
||||
|
||||
<p>
|
||||
<?php wp_nonce_field( 'save_account_details', 'save-account-details-nonce' ); ?>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* @see https://woo.com/document/template-structure/
|
||||
* @package WooCommerce\Templates
|
||||
* @version 2.6.0
|
||||
* @version 8.7.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
@ -65,6 +65,14 @@ $col = 1;
|
|||
<address>
|
||||
<?php
|
||||
echo $address ? wp_kses_post( $address ) : esc_html_e( 'You have not set up this type of address yet.', 'woocommerce' );
|
||||
|
||||
/**
|
||||
* Used to output content after core address fields.
|
||||
*
|
||||
* @param string $name Address type.
|
||||
* @since 8.7.0
|
||||
*/
|
||||
do_action( 'woocommerce_my_account_after_my_address', $name );
|
||||
?>
|
||||
</address>
|
||||
</div>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* @see https://woo.com/document/template-structure/
|
||||
* @package WooCommerce\Templates
|
||||
* @version 5.6.0
|
||||
* @version 8.7.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
@ -40,6 +40,17 @@ $show_shipping = ! wc_ship_to_billing_address_only() && $order->needs_shipping_a
|
|||
<?php if ( $order->get_billing_email() ) : ?>
|
||||
<p class="woocommerce-customer-details--email"><?php echo esc_html( $order->get_billing_email() ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Action hook fired after an address in the order customer details.
|
||||
*
|
||||
* @since 8.7.0
|
||||
* @param string $address_type Type of address (billing or shipping).
|
||||
* @param WC_Order $order Order object.
|
||||
*/
|
||||
do_action( 'woocommerce_order_details_after_customer_address', 'billing', $order );
|
||||
?>
|
||||
</address>
|
||||
|
||||
<?php if ( $show_shipping ) : ?>
|
||||
|
@ -54,6 +65,17 @@ $show_shipping = ! wc_ship_to_billing_address_only() && $order->needs_shipping_a
|
|||
<?php if ( $order->get_shipping_phone() ) : ?>
|
||||
<p class="woocommerce-customer-details--phone"><?php echo esc_html( $order->get_shipping_phone() ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Action hook fired after an address in the order customer details.
|
||||
*
|
||||
* @since 8.7.0
|
||||
* @param string $address_type Type of address (billing or shipping).
|
||||
* @param WC_Order $order Order object.
|
||||
*/
|
||||
do_action( 'woocommerce_order_details_after_customer_address', 'shipping', $order );
|
||||
?>
|
||||
</address>
|
||||
</div><!-- /.col-2 -->
|
||||
|
||||
|
|
Loading…
Reference in New Issue