I'm trying to wrap the billing state and billing country fields on checkout in a div but seems to not work. This my code:
<div class="woocommerce-billing-fields__field-wrapper">
<?php
$fields = $checkout->get_checkout_fields( 'billing' );
foreach ( $fields as $key => $field ) {
if($key == 'billing_state'){
} else if($key == 'billing_country'){
} else{
woocommerce_form_field( $key, $field, $checkout->get_value( $key ) );
}
}
?>
<div class="state-province">
<?php woocommerce_form_field( "billing_state", $checkout->checkout_fields['billing']['billing_state'], $checkout->get_value( 'billing_state' ) ); ?>
<?php woocommerce_form_field( "billing_country", $checkout->checkout_fields['billing']['billing_country'], $checkout->get_value( 'billing_country' ) ); ?>
</div>
</div>
I found a solution disabling class 'form-row' to avoid js from woocommerce and adding priority:
function change_woocommerce_field_markup($field, $key, $args, $value) {
$field = str_replace('form-row', '', $field);
$field = '<div class="single-field-wrapper" data-priority="' . $args['priority'] .
'">' . $field . '</div>';
if($key === 'billing_state')
$field = '<div class="state-province">'.$field;
else if ($key === 'billing_country')
$field = $field.'</div>';
return $field;
}
add_filter("woocommerce_form_field","change_woocommerce_field_markup", 10, 4);
Here is the explanation: https://wordpress.stackexchange.com/questions/309700/how-to-hook-on-a-woocommerce-checkout-field/309788
Related
Based on Get product custom attributes to display them in WooCommerce product loop answer code.
I am displaying specific product attributes on the single product page with this:
add_action('woocommerce_single_product_summary', 'display_custom_attributes', 36 );
function display_custom_attributes() {
global $product;
$attributes_names = array('Brand', 'Color', 'Size');
$attributes_data = array();
foreach ( $attributes_names as $attribute_name ) {
if ( $value = $product->get_attribute($attribute_name) ) {
$attributes_data[] = $attribute_name . ': ' . $value;
}
}
if ( ! empty($attributes_data) ) {
echo '<h4>Details</h4><ul><li>' . implode( '</li><li>', $attributes_data ) . '</ul>';
}
Now I also need to add two custom meta fields ('Serial_Number' and 'MPN') to this list.
How can I add these?
To add two custom meta fields:
Serial_Number
MPN
to this list, you can use:
function action_woocommerce_single_product_summary() {
global $product;
$attributes_names = array( 'Brand', 'Color', 'Size' );
$attributes_data = array();
foreach ( $attributes_names as $attribute_name ) {
if ( $value = $product->get_attribute($attribute_name) ) {
$attributes_data[] = $attribute_name . ': ' . $value;
}
}
// NOT empty
if ( ! empty($attributes_data) ) {
echo '<h4>' . __( 'Details', 'woocommerce' ) . '</h4><ul><li>' . implode( '</li><li>', $attributes_data );
}
// Get meta
$sn = $product->get_meta( 'Serial_Number' );
$mpn = $product->get_meta( 'MPN' );
// NOT empty
if ( ! empty ( $sn ) ) {
echo '<li>' . __( 'My label 1: ', 'woocommerce' ) . $sn . '</li>';
}
// NOT empty
if ( ! empty ( $mpn ) ) {
echo '<li>' . __( 'My label 2: ', 'woocommerce' ) . $mpn . '</li>';
}
echo '</ul>';
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 36, 0 );
Add this code on the function.php theme file
function call_product_meta_data()
{
global $post;
if ($post) {
$post_meta_value = get_post_meta($post->ID, 'post_meta_key', true);
if ($post_meta_value != null) {
echo "<div class='pr-meta'><p><strong>Meta Title</strong>: $post_meta_value</p></div>";
} else {
echo "<div class='pr-meta'><p><strong>Meta Title</strong>: N/A</p></div>";
}
}
}
add_action('woocommerce_single_variation', 'call_product_meta_data');
Can anyone let me know, how can i add / set filter by company name in woo-commerce order page.
and please share functions or show my error so i can solved it.
i tried it but not working. you help is much appreciated.
add_action( 'restrict_manage_posts', 'admin_shop_order_by_product_type_filter' );
function admin_shop_order_by_product_type_filter(){
global $pagenow, $post_type;
if( 'shop_order' === $post_type && 'edit.php' === $pagenow ) {
$domain = 'woocommerce';
$filter_id = 'filter_billing_company';
$current = isset($_GET[$filter_id])? $_GET[$filter_id] : '';
$query_args = ['fields' => '_billing_company', 'orderby' => 'order'];
echo "<pre>";print_r(get_terms($query_args)); echo "</pre>";
echo '<select name="'.$filter_id.'">
<option value="">' . __('Filter by Company', $domain) . '</option>';
foreach ( get_terms($query_args) as $term_name ) {
printf( '<option value="%s"%s>%s</option>', $term_name,
$term_name === $current ? '" selected="selected"' : '', ucfirst($term_name) );
}
echo '</select>';
}
}
Thanks
To filter orders by meta fields on admin orders list, you will use the following (where you will define in the 1st function below the metakey / label pairs that will filter orders):
// Custom function where metakeys / labels pairs are defined
function get_filter_shop_order_meta( $domain = 'woocommerce' ){
// Add below the metakey / label pairs to filter orders
return [
'_billing_company' => __('Billing company', $domain),
'_order_total' => __('Gran total', $domain),
];
}
// Add a dropdown to filter orders by meta
add_action( 'restrict_manage_posts', 'display_admin_shop_order_by_meta_filter' );
function display_admin_shop_order_by_meta_filter(){
global $pagenow, $typenow;
if( 'shop_order' === $typenow && 'edit.php' === $pagenow ) {
$domain = 'woocommerce';
$filter_id = 'filter_shop_order_by_meta';
$current = isset($_GET[$filter_id])? $_GET[$filter_id] : '';
echo '<select name="'.$filter_id.'">
<option value="">' . __('Filter by meta…', $domain) . '</option>';
$options = get_filter_shop_order_meta( $domain );
foreach ( $options as $key => $label ) {
printf( '<option value="%s"%s>%s</option>', $key,
$key === $current ? '" selected="selected"' : '', $label );
}
echo '</select>';
}
}
// Process the filter dropdown for orders by Marketing optin
add_filter( 'request', 'process_admin_shop_order_marketing_by_meta', 99 );
function process_admin_shop_order_marketing_by_meta( $vars ) {
global $pagenow, $typenow;
$filter_id = 'filter_shop_order_by_meta';
if ( $pagenow == 'edit.php' && 'shop_order' === $typenow
&& isset( $_GET[$filter_id] ) && ! empty($_GET[$filter_id]) ) {
$vars['meta_key'] = $_GET[$filter_id];
$vars['orderby'] = 'meta_value';
}
return $vars;
}
// (Optional) Make a custom meta field searchable from the admin order list search field
add_filter( 'woocommerce_shop_order_search_fields', 'shop_order_meta_search_fields', 10, 1 );
function shop_order_meta_search_fields( $meta_keys ){
foreach ( get_filter_shop_order_meta() as $meta_key => $label ) {
$meta_keys[] = $meta_key;
}
return $meta_keys;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I added a custom <select> field to each product in cart page to be able to update variation, but when I change it's value and click "Update Cart", nothing updates unless quantity field has also been changed.
Is there a way to avoid this?
My code:
functions.php file:
add_filter( 'woocommerce_update_cart_action_cart_updated', 'on_action_cart_updated', 20, 1 );
function on_action_cart_updated( $cart_updated ){
if ($cart_updated) {
$cart_content = WC()->cart->get_cart_contents();
$update_cart = false;
$cart_totals = isset( $_POST['cart'] ) ? wp_unslash( $_POST['cart'] ) : '';
if ( ! empty( $cart_content ) && is_array( $cart_totals ) ) {
foreach ($cart_content as $key => $item) {
$lease_period = $cart_totals[$key]['lease'];
if ( ! empty( $lease_period )) {
$cart_content[$key]['variation']['attribute_pa_lease-period'] = $lease_period;
$update_cart = true;
}
}
if ($update_cart) {
WC()->cart->set_cart_contents($cart_content);
}
}
}
}
cart.php file:
<td class="product-lease-period" data-title="<?php esc_attr_e( 'Lease Period', 'woocommerce' ); ?>">
<div class="product-lease-period-select">
<select name="cart[<?php echo $cart_item_key ?>][lease]">
<?php
$lease_periods = ['6-months'=> '6 Months',
'12-months' => '12 Months',
'18-months' => '18 Months',
'24-months' => '24 Months'];
foreach ($lease_periods as $key => $period) {
$selected = '';
if ($cart_item['variation']['attribute_pa_lease-period'] == $key) {
$selected = 'selected="selected"';
}
echo "<option value=" . $key . " $selected>" . $period . "</option>";
}
?>
</select>
</div>
</td>
My conclusions so far:
I believe it's because of these pieces of code inside the class-wc-form-handler.php :
// Skip product if no updated quantity was posted.
if ( ! isset( $cart_totals[ $cart_item_key ] ) || ! isset( $cart_totals[ $cart_item_key ]['qty'] ) ) {
continue;
}
and a bit below:
if ( '' === $quantity || $quantity === $values['quantity'] ) {
continue;
}
I extended the WC_Form_Handler class in my functions.php file, copied a method I needed and edited it, and gave it higher hook priority in my extended class than it's in the original class:
class WC_Form_Handler_Ext extends WC_Form_Handler {
/**
* Hook in method.
*/
public static function init() {
add_action( 'wp_loaded', array( __CLASS__, 'update_cart_action' ), 30 );
}
/**
* Remove from cart/update.
*/
public static function update_cart_action() {
// method content edited
}
}
WC_Form_Handler_Ext::init();
UPDATE:
To make price change after variation value in cart is updated, this function needs to be added to the functions.php
function find_matching_product_variation_id($product_id, $attributes)
{
return (new WC_Product_Data_Store_CPT())->find_matching_product_variation(
new WC_Product($product_id),
$attributes
);
}
And it should be called from the loop in functions.php I mentioned in my question this way:
$attributes = $cart_content[$key]['variation'];
$variation_id = find_matching_product_variation_id($product_id, $attributes);
$price = get_post_meta($variation_id, '_price', true);
$item['data']->set_price($price);
Ask to everyone, i have problem. Here i try to use multiple chechbox to my custom post metabox.
<?php
function prodetail() {
add_meta_box('pro_metabox', 'Detail Property', 'pro_metabox', 'property', 'normal', 'default');
}
function pro_metabox() {
global $post;
echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
$postmeta = maybe_unserialize( get_post_meta( $post->ID, 'elements', true ) );
$elements = array(
'pool' => 'Pool',
'garage' => 'Garage',
'balcon' => 'Balcon',
'yard' => 'Yard',
'internet' => 'Internet'
);
foreach ( $elements as $id => $element) {
if ( is_array( $postmeta ) && in_array( $id, $postmeta ) ) {
$checked = 'checked="checked"';
} else {
$checked = null;
}
?>
<div class="pro-inn">
<div class="procols">
<div class="pro-inn">
<input type="checkbox" name="multval[]" value="<?php echo $id; ?>" <?php echo $checked; ?> />
<?php echo $element;?>
</div>
</div>
</div>
<?php
}
}
function pro_meta($post_id, $post) {
if ( !wp_verify_nonce( $_POST['eventmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
if ( ! empty( $_POST['multval'] ) ) {
update_post_meta( $post_id, 'elements', $_POST['multval'] );
} else {
delete_post_meta( $post_id, 'elements' );
}
}
add_action('save_post', 'pro_meta', 1, 2);
?>
help me to add code to show this checked result to single.php because my code use foreach just show Array text not show text like Pool Garage Balcon ect.
Thanks
Use this code in your single.php file for your custom post
$meta_value = get_post_meta( $post->ID, 'elements', true );
foreach($meta_value as $key=>$value){
echo $value . ' ';
}
It will show results same as you mentioned in the question ie:
(Pool Garage Balcon ect.)
So I've been playing around with some custom metaboxes and following tutorials etc - I've got to the point where the top metabox field is saving correctly but the second one (width) doesn't save - is there anything obvious I'm doing wrong here? I've tried separating the second field's save in to a separate function to test but that also did not work.
add_action( 'add_meta_boxes', 'youtube_metaboxes' );
function youtube_metaboxes() {
add_meta_box('wpt_youtube', 'youtube URL', 'wpt_youtube', 'product', 'side', 'default');
}
function wpt_youtube() {
global $post;
echo '<input type="hidden" name="youtubemeta_noncename" id="youtubemeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
$addyoutube = get_post_meta($post->ID, '_youtube', true);
echo '<input type="text" name="_youtube" value="' . $addyoutube . '" class="widefat" />';
$youtubeWidth = get_post_meta($post->ID, '_width', true);
echo 'Width: <br /><input type="text" name="_width" value="' . $youtubeWidth . '" class="widefat" />';
}
// Save the Metabox Data
function wpt_save_youtube_meta($post_id, $post) {
if ( !wp_verify_nonce( $_POST['youtubemeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
$addyoutube_meta['_youtube'] = $_POST['_youtube'];
foreach ($addyoutube_meta as $key => $value) {
if( $post->post_type == 'revision' ) return;
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) {
update_post_meta($post->ID, $key, $value);
} else {
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key);
}
$addWidth_meta['_width'] = $_POST['_width'];
foreach ($addWidth_meta as $key => $value) {
if( $post->post_type == 'revision' ) return;
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) {
update_post_meta($post->ID, $key, $value);
} else {
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key);
}
}
add_action('save_post', 'wpt_save_youtube_meta', 1, 2); // save the custom fields
I had a look through this article:
http://wp.tutsplus.com/tutorials/reusable-custom-meta-boxes-part-1-intro-and-basic-fields/
Seems like a much better way of creating custom meta boxes.