Wordpress/WooCommerce Registration - wordpress

I'm using a plugin (User Profiles Made Easy) that allows a user to choose their own role when registering on my website. It does a good job with that, but what it doesn't do is allow me to conditionally show/hide other fields based on the role they choose.
I thought of Gravity Form and their User Registration add-on, but it won't allow the user to choose their own role when registering.
The WooCommerce tie-in is this: When the buyer checks out, I could collect the extra data at that time (instead of during registration), but I would want to only show the fields relevant to their chosen role. Any ideas?

Borrowing from my tutorial on cutomizing WooCommerce checkout I think we can just wrap certain fields role/capability conditional logica via current_user_can().
// Add a new checkout field
function kia_filter_checkout_fields($fields){
if( current_user_can('some_capability' ) ){
$fields['extra_fields'] = array(
'some_field' => array(
'type' => 'text',
'required' => true,
'label' => __( 'Some field' )
)
);
}
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'kia_filter_checkout_fields' );
// display the extra field on the checkout form
function kia_extra_checkout_fields(){
if( current_user_can('some_capability' ) ){
$checkout = WC()->checkout(); ?>
<div class="extra-fields">
<h3><?php _e( 'Additional Fields' ); ?></h3>
<?php foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
<?php } ?>
</div>
<?php }
add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );
// save the extra field when checkout is processed
function kia_save_extra_checkout_fields( $order_id, $posted ){
if( current_user_can( 'some_capability' && isset( $posted['some_field'] ) ) {
update_post_meta( $order_id, '_some_field', sanitize_text_field( $posted['some_field'] ) );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'kia_save_extra_checkout_fields', 10, 2 );
// display the extra data on order recieved page and my-account order review
function kia_display_order_data( $order_id ){
if( current_user_can('some_capability' ) ){
?>
<h2><?php _e( 'Additional Info' ); ?></h2>
<table class="shop_table shop_table_responsive additional_info">
<tbody>
<tr>
<th><?php _e( 'Some Field:' ); ?></th>
<td data-title="Telephone"><?php echo get_post_meta( $order_id, '_some_field', true ); ?></td>
</tr>
</tbody>
</table>
<?php }
}
add_action( 'woocommerce_thankyou', 'kia_display_order_data', 20 );
add_action( 'woocommerce_view_order', 'kia_display_order_data', 20 );
// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order ){
if( current_user_can('some_capability' ) ){
?>
<div class="order_data_column">
<h4><?php _e( 'Extra Details', 'woocommerce' ); ?></h4>
<?php
echo '<p><strong>' . __( 'Some field' ) . ':</strong>' . get_post_meta( $order->id, '_some_field', true ) . '</p>'; ?>
</div>
<?php }
}
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );

Related

Add editable address fields to WooCommerce invoice page

Please forgive such a basic question. I'm relatively new to WooCommerce theme development and genuinely trying to understand how wordpress handles customer data so I can learn how to manipulate it. If this question is still too broad, (My previous question was closed for that reason) I'd even welcome a few links which help point me in the correct direction and explain the area I'm looking at.
What I am trying to do is add editable address fields to the page customers see when we email them an invoice. (form-pay.php)
Initially, I tried adding fields manually using variation on the following code for each field in functions.php and calling it in from order-pay.php:
<p class="form-row form-row-first">
<label for="billing_first_name"><?php _e( 'First name', 'woocommerce' ); ?><span class="required">*</span></label>
<input type="text" class="input-text" name="billing_first_name" id="billing_first_name" value="<?php if ( ! empty( $_POST['billing_first_name'] ) ) esc_attr_e( $_POST['billing_first_name'] ); ?>" />
</p>
However, when I do it this way, it adds the address details associated with my own WordPress login, rather than the customer's address associated with the invoice.
I have worked through the woocommerce codex on hooks and filters and also found the answer to this question which allowed the correct address fields to be added.
This is where my question seems to differ from a lot of the solutions I've found, in that most solutions are for updating the billing and shipping address of the current cart or logged in user, rather than that associated with a specific invoice.
Here's the fields I've added to form-pay.php.
<h2 class="woocommerce-column__title"><?php esc_html_e( 'Billing address', 'woocommerce' ); ?></h2>
<address>
<?php echo wp_kses_post( $order->get_formatted_billing_address( __( 'N/A', 'woocommerce' ) ) ); ?>
<?php if ( $order->get_billing_phone() ) : ?>
<p class="woocommerce-customer-details--phone"><?php echo esc_html( $order->get_billing_phone() ); ?></p>
<?php endif; ?>
<?php if ( $order->get_billing_email() ) : ?>
<p class="woocommerce-customer-details--email"><?php echo esc_html( $order->get_billing_email() ); ?></p>
<?php endif; ?>
</address>
<h2 class="woocommerce-column__title"><?php esc_html_e( 'Shipping address', 'woocommerce' ); ?></h2>
<address>
<?php echo wp_kses_post( $order->get_formatted_shipping_address( __( 'N/A', 'woocommerce' ) ) ); ?>
</address>
<!-- Form -->
<h3><?php _e( 'Billing details', 'woocommerce' ); ?></h3>
<?php do_action( 'woocommerce_before_checkout_billing_form', $order ); ?>
<div class="woocommerce-billing-fields__field-wrapper">
<?php
$fields = WC()->checkout->get_checkout_fields( 'billing' );
foreach ( $fields as $key => $field ) {
$field_name = $key;
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
$field['value'] = $order->{"get_$field_name"}( 'edit' );
} else {
$field['value'] = $order->get_meta( '_' . $field_name );
}
woocommerce_form_field( $key, $field, $field['value'] );
}
?>
</div>
<?php do_action( 'woocommerce_after_checkout_billing_form', $order ); ?>
<h3><?php _e( 'Shipping details', 'woocommerce' ); ?></h3>
<?php do_action( 'woocommerce_before_checkout_shipping_form', $order ); ?>
<div class="woocommerce-shipping-fields__field-wrapper">
<?php
$fields = WC()->checkout->get_checkout_fields( 'shipping' );
foreach ( $fields as $key => $field ) {
$field_name = $key;
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
$field['value'] = $order->{"get_$field_name"}( 'edit' );
} else {
$field['value'] = $order->get_meta( '_' . $field_name );
}
woocommerce_form_field( $key, $field, $field['value'] );
}
?>
</div>
<?php do_action( 'woocommerce_after_checkout_shipping_form', $order ); ?>
The fields correctly appear on the invoice page now which display all address details I have already added to the invoice. I just need to understand what logic I need to attach to a button to tell WooCommerce to update the record.
As I said, I recognise this is a fundamentally basic question, but so far I've failed to find an explanation that works specifically in the context of updating the invoice rather than the cart.

How to get pages as a checkbox option in user profile

i want to list the pages in checkbox in user profile for the users role to check specified page for them
function my_user_field( $user ) {
$user_meta = get_the_author_meta( 'user_interests', $user->ID, true );?>
<table class="form-table">
<tr>
<th>
<label for="Dealing Type">Multi pages select for blurbs
</label></th><td>
<?php
$mypages = get_pages( array(
'sort_column' => 'post_date',
'sort_order' => 'desc'
) );
if(count($mypages)){
foreach( $mypages as $page )
{
$title = $page->post_title;
$slug = $page->post_name;
?>
<label for='user_interests_<?php echo $page->post_name; ?>' class='blurb_user_label_checkbox'>
<input id='user_interests_<?php echo $page->post_name; ?>' name='user_interests[<?php echo $page->post_title; ?>]' type='checkbox' value='$page->post_title'
<?php if ( in_array( $page->post_title, $user_meta ) ) echo ' checked="checked"'; ?> class='blurb_user_checkbox'>
<?Php echo $title; ?>
</label>
<?php
}
}
var_dump($user_meta);
?>
</td>
</tr>
</table>
function my_save_custom_user_profile_fields( $user_id ) {
if ( !current_user_can( 'edit_user', $user_id ) )
return FALSE;
update_usermeta( $user_id, 'user_interests', $_POST['user_interests']);
}
add_action( 'user_new_form', 'my_user_field' );
add_action( 'show_user_profile', 'my_user_field' );
add_action( 'edit_user_profile', 'my_user_field' );
add_action( 'personal_options_update', 'my_save_custom_user_profile_fields' );
add_action( 'edit_user_profile_update', 'my_save_custom_user_profile_fields' );
add_action('user_register', 'my_save_custom_user_profile_fields');
The checkbox is not working when options saved so please help me somebody. i hope guys you can help me.if there any other methods also please give me

Display content on single product page in Woocommerce based on category

I'm sooooo close - but I can't get this last little bit.
I am adding the authors name to books we have for sale in woo. The style needs to be different from the book title so I'm using a custom meta field to put it under the title and style it the way I want. I have everything working and where I want it, now I just need for it only show on a particular category instead of on all products.
There seems to me to be two ways to do this.
1 - Only display it for products in a particular category
2 - Only display it if there is content.
I'm currently trying to only display if it's a particular category, but while writing this, its seems a more elegant solution to only display if content exists.
Here's what I have
function cn_add_add_subhead_to_title() {
global $woocommerce, $post;
if ( is_product() && has_term( 'books-media', 'product_cat' ) ) {
?>
<div class="cn-subhead">
by <?php echo get_post_meta( $post->ID, '_text_field', true ); ?>
</div>
<?php
}
}
add_action( 'woocommerce_single_product_summary', 'cn_add_add_subhead_to_title', 6 );
This doesn't display anywhere, but when I take out the if statement it shows on all products.
Any idea where I went awry?
Here is the answer in context Helga - this snippet will add a custom meta field to the woocommerce product editing dashboard, save the content and display it under the product title on the single product view.
/* add product subhead custom field to woocommerce product dashboard */
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
woocommerce_wp_text_input(
array(
'id' => '_text_field',
'label' => __( 'MY-LABEL', 'woocommerce' ),
'placeholder' => 'Author',
'desc_tip' => 'true',
'description' => __( 'This text will show below the product title.', 'woocommerce' )
)
);
echo '</div>';
}
/* Save woo custom field */
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields_save( $post_id ){
$woocommerce_text_field = $_POST['_text_field'];
if( !empty( $woocommerce_text_field ) )
update_post_meta( $post_id, '_text_field', esc_attr( $woocommerce_text_field ) );
}
/* add author below title on single product */
function cn_add_subhead_to_title() {
global $woocommerce, $post;
$meta = get_post_meta( $post->ID, '_text_field', true );
if( $meta != '' ) {
?>
<div class="cn-subhead">
by <?php echo get_post_meta( $post->ID, '_text_field', true ); ?>
</div>
<?php
}
}
add_action( 'woocommerce_single_product_summary', 'cn_add_subhead_to_title', 6 );
What if you simply test for the presence of the meta? If you don't save the meta in the other categories it will never display:
function cn_add_add_subhead_to_title() {
global $post;
if ( $meta = get_post_meta( $post->ID, '_text_field', true ) ) {
?>
<div class="cn-subhead">
<?php printf( __( 'by %s', 'textdomain' ), $meta ); ?>
</div>
<?php
}
}
add_action( 'woocommerce_single_product_summary', 'cn_add_add_subhead_to_title', 6 );
Helga - Thanks for your interest and help. I had a little time so I decided to try the other route of only displaying the meta if there was content instead of based on category. This may be a more flexible solution anyway, leaving the field open to any sort of subhead they want instead of limiting it only to Authors.
This the code that worked:
/* add author below title on single product */
function cn_add_add_subhead_to_title() {
global $woocommerce, $post;
$meta = get_post_meta( $post->ID, '_text_field', true );
if( $meta != '' ) {
?>
<div class="cn-subhead">
by <?php echo get_post_meta( $post->ID, '_text_field', true ); ?>
</div>
<?php
}
}
add_action( 'woocommerce_single_product_summary', 'cn_add_add_subhead_to_title', 6 );

How to arrange the custom field on woocommerce checkout page

I know how to add a custom field to the checkout page, and then how to process the field also.
But when I add a custom field to my form, it always appears at the end of the form. How can I make it appear on top of other fields?
My current script:
<?php *// Add a new checkout field
function kia_filter_checkout_fields($fields){
$fields['extra_fields'] = array(
'message_field' => array(
'type' => 'textarea',
'required' => true,
'label' => __( 'Message Field' )
),
);
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'kia_filter_checkout_fields' );
// display the extra field on the checkout form
function kia_extra_checkout_fields(){
$checkout = WC()->checkout(); ?>
<div class="extra-fields">
<h3><?php _e( 'WRITE A MESSAGE TO RECIPIENT' ); ?><span>(<?php _e( 'Leave blank if not required' ); ?>)</span></h3>
<?php
// because of this foreach, everything added to the array in the previous function will display automagically
foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
</div>
<?php }
add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );
// save the extra field when checkout is processed
function kia_save_extra_checkout_fields( $order_id, $posted ){
// don't forget appropriate sanitization if you are using a different field type
if( isset( $posted['message_field'] ) ) {
update_post_meta( $order_id, '_message_field', sanitize_text_field( $posted['message_field'] ) );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'kia_save_extra_checkout_fields', 10, 1);
// display the extra data on order recieved page and my-account order review
function kia_display_order_data( $order_id ){ ?>
<h2><?php _e( 'Additional Info' ); ?></h2>
<table class="shop_table shop_table_responsive additional_info">
<tbody>
<tr>
<th><?php _e( 'message_field:' ); ?></th>
<td><?php echo get_post_meta( $order_id, '_message_field', true ); ?></td>
</tr>
<tr>
</tr>
</tbody>
</table>
<?php }
add_action( 'woocommerce_thankyou', 'kia_display_order_data', 20 );
add_action( 'woocommerce_view_order', 'kia_display_order_data', 20 );
// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order ){ ?>
<div class="order_data_column">
<h4><?php _e( 'Extra Details', 'woocommerce' ); ?></h4>
<?php
echo '<p><strong>' . __( 'Some field' ) . ':</strong>' . get_post_meta( $order->id, '_message_field', true ) . '</p>';
// echo '<p><strong>' . __( 'Another field' ) . ':</strong>' . get_post_meta( $order->id, '_another_field', true ) . '</p>'; ?>
</div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );
?>*
Instead of hooking into woocommerce_checkout_after_customer_details you need to hook into woocommerce_checkout_before_customer_details, that way your custom field will appear on top of other fields.
So change the following line of code
add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );
to
add_action( 'woocommerce_checkout_before_customer_details' ,'kia_extra_checkout_fields' );
Please try to remove class="extra-fields"
<div id="my_custom_checkout_field">
<h3><?php _e( 'WRITE A MESSAGE TO RECIPIENT' ); ?><span>(<?php _e( 'Leave blank if not required' ); ?>)</span></h3>
<?php
// because of this foreach, everything added to the array in the previous function will display automagically
foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
</div>
I have used it with id and it works well for me. Like this

Add a step to WooCommerce Checkout

Is there any way to add a new step to the Checkout process in WooCommerce? I need something between the cart and the Billing Details page to collect some additional information. I've researched quite a bit and turned up nothing. I can't be the only person who wants to do this.
From my tutorial on WooCommerce Custom Checkout Fields this is how to add a custom checkout field which you could use to collect additional information.
// Add a new checkout field
function kia_filter_checkout_fields($fields){
$fields['extra_fields'] = array(
'some_field' => array(
'type' => 'text',
'required' => true,
'label' => __( 'Some field' )
)
);
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'kia_filter_checkout_fields' );
// display the extra field on the checkout form
function kia_extra_checkout_fields(){
$checkout = WC()->checkout(); ?>
<div class="extra-fields">
<h3><?php _e( 'Additional Fields' ); ?></h3>
<?php foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
</div>
<?php }
add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );
// save the extra field when checkout is processed
function kia_save_extra_checkout_fields( $order_id, $posted ){
if( isset( $posted['some_field'] ) ) {
update_post_meta( $order_id, '_some_field', sanitize_text_field( $posted['some_field'] ) );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'kia_save_extra_checkout_fields', 10, 2 );
// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order ){ ?>
<div class="order_data_column">
<h4><?php _e( 'Extra Details', 'woocommerce' ); ?></h4>
<?php
echo '<p><strong>' . __( 'Some field' ) . ':</strong>' . get_post_meta( $order->id, '_some_field', true ) . '</p>'; ?>
</div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );

Resources