Update customer password in WooCommerce admin orders dashboard
Here is a complete solution that will add in admin orders list a custom column with a button (in each row) allowing editing the user password via Ajax.
Then when shop manager will click on the button of the desired order, an input text field will appear where the new password can be updated via Ajax.
A message will be shortly displayed showing if this update has succeeded or not.
So here is the complete code:
// Add a column to admin orders list
add_filter( 'manage_edit-shop_order_columns', 'add_edit_password_orders_column' );
function add_edit_password_orders_column( $columns ) {
if( current_user_can( 'edit_shop_orders' ) ) {
$sorted_columns = [];
foreach ( $columns as $key => $value ) {
if ( $key === 'order_total') {
$sorted_columns[ 'edit_password' ] = __('Edit password', 'woocommerce');
}
$sorted_columns[$key] = $columns[$key];
}
return $sorted_columns;
}
return $columns;
}
// Column content
add_action( 'manage_shop_order_posts_custom_column', 'edit_password_orders_column_row_content' );
function edit_password_orders_column_row_content( $column ) {
if ( 'edit_password' === $column ) {
global $post, $the_order;
$user = $the_order->get_user();
if( is_a($user, 'WP_User') && $user->ID > 0 ) {
echo '<div class="edit_password userid-' . $user->ID . '" data-user_id="' . $user->ID . '">
<a class="button user-login" style="text-align:center; display:block;">' . __('Edit', 'woocommerce') . '</a>
<div class="hidden-fields" style="display:none;">
<input type="text" name="customer-password" class="customer-password" value="" style="width:auto; max-width:120px; margin-bottom: 6px;">
<input type="hidden" name="customer-id" class="customer-id" value="' . $user->ID . '">
<a class="button submit-password" style="text-align:center;">' . __('Ok', 'woocommerce') . '</a>
</div>
<div class="message-response" style="display:none;">Message</div>
</div>';
} else {
echo __("Guest user", "woocommerce");
}
}
}
// Jquery Ajax
add_action( 'admin_footer', 'edit_password_orders_column_js' );
function edit_password_orders_column_js() {
global $pagenow;
if ( $pagenow === 'edit.php' && isset($_GET['post_type']) && 'shop_order' === $_GET['post_type'] ) :
?>
<script type="text/javascript">
jQuery( function($){
$('div.edit_password > .button.user-login').on('click', function(e){
e.preventDefault();
$(this).hide('fast');
$(this).parent().find('.hidden-fields').show('slow');
});
$(document.body).on('click focus focusin', 'div.edit_password input.customer-password', function(e){
e.stopImmediatePropagation();
});
$('div.edit_password .button.submit-password').on('click', function(e){
e.preventDefault();
e.stopImmediatePropagation();
var $this = $(this),
$parent = $this.parent(),
password = $parent.find('input.customer-password').val(),
user_id = $parent.find('input.customer-id').val(),
text = '',
color = 'red';
$.ajax({
type: 'POST',
url: '<?php echo admin_url('/admin-ajax.php'); ?>',
data: {
'action' : 'updating_customer_password',
'customer-password': password,
'customer-id' : user_id
},
success: function (response) {
if ( response === 'empty' ) {
text = '<?php echo __('Empty input, retry…', 'woocommerce'); ?>';
} else if ( response === 'whitespace' ) {
text = '<?php echo __('No white spaces…', 'woocommerce'); ?>';
} else {
text = '<?php echo __('Updating password!', 'woocommerce'); ?>';
color = 'green';
}
$parent.find('input.customer-password').val('');
$parent.parent().find('.hidden-fields').hide('fast');
$parent.parent().find('div.message-response').css('color',color).html('<small>'+text+'<small>').show();
setTimeout(function(){
$parent.parent().find('div.message-response').css('color','black').html('').hide();
$parent.parent().find('a.user-login').show();
}, 2000);
console.log(response); // For testing (to be removed)
},
error: function (error) {
$this.parent().parent().find('.hidden-fields').hide('fast');
$this.parent().parent().find('div.message-response').html('Error!').css('color',color).show();
setTimeout(function(){
$parent.parent().find('div.message-response').css('color','black').html('').hide();
$parent.parent().find('a.user-login').show();
}, 2000);
console.log(error); // For testing (to be removed)
}
});
});
});
</script>
<?php
endif;
}
// PHP Ajax receiver
add_action('wp_ajax_updating_customer_password', 'action_ajax_updating_customer_password');
function action_ajax_updating_customer_password() {
if ( isset($_POST['customer-password']) && isset($_POST['customer-id']) ) {
$password = sanitize_text_field( $_POST['customer-password'] );
$user_id = intval( esc_attr( $_POST['customer-id'] ) );
if ( ! $password ) {
echo 'empty'; // empty input
} elseif ( strpos($password, ' ') !== false ) {
echo 'whitespace'; // empty input
} else {
wp_set_password( $password, $user_id ); // Set new password
}
wp_die();
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
This will help you to add a new column in the order list table - that contains the link to edit user of the corresponding customer.
function wc_new_order_column( $columns ) {
$columns[ 'customer' ] = 'Customer';
return $columns;
}
add_filter( 'manage_edit-shop_order_columns', 'wc_new_order_column' );
function add_order_name_column_content( $column ) {
global $post;
if ( 'customer' === $column ) {
$order = wc_get_order( $post->ID );
$link = get_edit_user_link($order->get_customer_id());
$name = $order->get_billing_first_name();
echo "<a target='_blank' href=".$link.">".$name."</a>";
}
}
add_action( 'manage_shop_order_posts_custom_column', 'add_order_name_column_content' );
Here is another similar way but this time on Admin single edit order pages with a custom Metabox on right side, using Ajax to update the customer password.
A message will be shortly displayed showing if this password update has succeeded or not disallowing empty password submissions or whitespaces in the password.
Here is the code:
// Adding a custom Metabox on WooCommerce single orders (on right side)
add_action( 'add_meta_boxes', 'add_custom_shop_order_metabox' );
function add_custom_shop_order_metabox(){
global $post;
$customer_id = get_post_meta( $post->ID, '_customer_user', true );
if ( $customer_id > 0 ) {
add_meta_box(
'custom_shop_order_metabox',
__('Change password', 'woocommerce'),
'content_custom_shop_order_metabox',
'shop_order',
'side',
'core'
);
}
}
// Custom Metabox content on WooCommerce single orders
function content_custom_shop_order_metabox() {
global $post;
$customer_id = get_post_meta( $post->ID, '_customer_user', true );
echo '<div class="options_group edit_password" style="min-height:4.5em;margin-top:12px;;">
<input type="text" name="customer-password" class="customer-password" value="">
<a class="button submit-password" style="text-align:center;">' . __('Submit', 'woocommerce') . '</a>
<input type="hidden" name="customer-id" class="customer-id" value="' . $customer_id . '">
<div class="message-response" style="margin-top:6px;"></div>
</div>';
}
// Jquery Ajax
add_action( 'admin_footer', 'edit_password_orders_column_js' );
function edit_password_orders_column_js() {
global $pagenow, $post_type;
if ( 'post.php' === $pagenow && 'shop_order' === $post_type ) :
?>
<script type="text/javascript">
jQuery( function($){
$('div.edit_password > .message-response').fadeOut(0);
$('div.edit_password > .button.submit-password').on('click', function(e){
e.preventDefault();
e.stopImmediatePropagation();
var $this = $(this),
$parent = $this.parent(),
password = $parent.find('.customer-password').val(),
user_id = $parent.find('.customer-id').val(),
text = '',
color = 'red';
$.ajax({
type: 'POST',
url: '<?php echo admin_url('/admin-ajax.php'); ?>',
data: {
'action' : 'updating_customer_password',
'customer-password': password,
'customer-id' : user_id
},
success: function (response) {
if ( response === 'empty' ) {
text = '<?php echo __('Empty input, retry…', 'woocommerce'); ?>';
} else if ( response === 'whitespace' ) {
text = '<?php echo __('No white spaces…', 'woocommerce'); ?>';
} else {
text = '<?php echo __('Password Updated!', 'woocommerce'); ?>';
color = 'green';
}
$parent.find('.customer-password').val('');
$parent.find('.message-response').html('<small>'+text+'<small>').css('color',color).fadeIn();
setTimeout(function(){
$parent.find('.message-response').fadeOut( function(){ $(this).css('color','black').html(''); });
}, 2000)
}
});
});
});
</script>
<?php
endif;
}
// PHP Ajax receiver
add_action('wp_ajax_updating_customer_password', 'action_ajax_updating_customer_password');
function action_ajax_updating_customer_password() {
if ( isset($_POST['customer-password']) && isset($_POST['customer-id']) ) {
$password = sanitize_text_field( $_POST['customer-password'] );
$user_id = intval( esc_attr( $_POST['customer-id'] ) );
if ( ! $password ) {
echo 'empty'; // empty input
} elseif ( strpos($password, ' ') !== false ) {
echo 'whitespace'; // empty input
} else {
wp_set_password( $password, $user_id ); // Set new password
}
wp_die();
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.