I am trying to add a custom metabox in woocommerce. It has been added perfectly. My ultimate goal is to call that custom field in a function and show it in the cart.php. So I coded :
For Custom field: [I would refer http://www.remicorson.com/mastering-woocommerce-products-custom-fields/] in this regard
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
// Save Fields
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
woocommerce_wp_text_input(
array(
'id' => 'number_field',
'label' => __( '<strong style="color:#239804">Your Free Products</strong>', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'Please enter a number', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
echo '</div>';
}//woo_add_custom_general_fields
function woo_add_custom_general_fields_save( $post_id ){
$woocommerce_number_field = $_POST['number_field'];
if( !empty( $woocommerce_number_field ) )
update_post_meta( $post_id, 'number_field', esc_attr( $woocommerce_number_field ) );
}//woo_add_custom_general_fields_save( $post_id )
It has perfectly fitted in the Product Admin Page. Now I am creating another function where I am creating a counter for cart.php
function free_products(){
global $woocommerce ,$product, $post;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$free_number = get_post_meta( $post->ID, 'number_field', true );
$free_product = $cart_item['quantity'] * $free_number;
echo apply_filters( 'woocommerce_cart_item_quantity', $free_product, $cart_item_key );
}
}
In My cart.php when I add
<td class="product-quantity">
<?php
echo free_products();
?>
</td>
The output become zero in front end. Can anyone please help me what I am going wrong. Thanks in advance.
Try below code :
function free_products(){
global $woocommerce ,$product, $post;
foreach ( WC()->cart->get_cart() as $cart_item ) {
$my_var = $cart_item['product_id'];
$free_number = get_post_meta( $my_var, 'number_field', true );
$free_product = $cart_item['quantity'] * $free_number;
echo apply_filters( 'woocommerce_cart_item_quantity', $free_product);
}
}
Let me know if It is working for you or not.Its working for me.
Related
I have made a custom field in the product card and displayed it in the catalogue, but the problem is that there is no link to go to the product card. I would appreciate any help.
Here is the code for adding a field in the product card
// Field Short name
add_action( 'woocommerce_product_options_general_product_data', 'shorttitle_custom_general_fields' );
add_action( 'woocommerce_process_product_meta', 'shorttitle_custom_general_fields_save' );
function shorttitle_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
woocommerce_wp_text_input(
array(
'id' => 'shorttitle_field',
'label' => __( 'Краткое название', 'woocommerce' ),
//'desc_tip' => 'true',
//'description' => __( 'Краткое название', 'woocommerce' ),
'type' => 'html'
)
);
echo '</div>';
}
function shorttitle_custom_general_fields_save( $post_id ){
// Text Field
$woocommerce_text_field = $_POST['shorttitle_field'];
if( !empty( $woocommerce_text_field ) )
update_post_meta( $post_id, 'shorttitle_field', esc_attr( $woocommerce_text_field ) );
}
This is the code for displaying this field on the catalogue page
// Change the output of the product header (in the catalogue)
remove_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title' );
add_action( 'woocommerce_shop_loop_item_title', 'custom_woocommerce_template_loop_product_title', 99 );
function custom_woocommerce_template_loop_product_title() {
global $post;
$product = wc_get_product( $post->ID );
$title = get_post_meta( $post->ID, 'shorttitle_field', true );
if( $title ) {
echo '<h2 class="woocommerce-loop-product__title">' . esc_html( $title ) . '</h2>';
} else {
echo '<h2 class="woocommerce-loop-product__title">' . esc_html( $product->get_title() ) . '</h2>';
}
}
Page https://www.krisstyle.com.ua/shop/
I am trying to display a custom admin order column in WooCommerce and I am having a hard time getting the code right here.
I have this code:
add_filter( 'woocommerce_admin_order_data_after_order_details', 'display_order_data_in_admin', 10, 1);
function display_order_data_in_admin( $output )
global $wp_query
$output .= wc_product_dropdown_categories( array(
'show_option_none' => 'Filter by Location',
'taxonomy => 'product_tag',
'name' => 'product_tag',
'selectd' => isset( $wp_query->query_vars['product_tag'] ) ? $wp_query->vars['procut_tag'] :
) );
return $output;
}
I am having a hard time displaying a column for filtering my orders by location that has been selected in checkout.
add_filter( 'manage_edit-shop_order_columns', 'wc_add_new_order_admin_list_column' );
function wc_add_new_order_admin_list_column( $columns ) {
$columns['billing_country'] = 'Country';
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'wc_add_new_order_admin_list_column_content' );
function wc_add_new_order_admin_list_column_content( $column ) {
global $post;
if ( 'billing_country' === $column ) {
$order = wc_get_order( $post->ID );
echo $order->get_billing_country();
}
}
Hi I would like to add country of origin while adding products and then sort products based on country of origin
Can I achieve this?
Add these functions to your theme's 'functions.php'.
Display & Save the Custom Field in Admin
// display field in admin
add_action('woocommerce_product_options_general_product_data', 'woocommerce_product_country_field');
function woocommerce_product_country_field()
{
global $woocommerce, $post;
$countries_obj = new WC_Countries();
$options = $countries_obj->__get('countries');
echo '<div class="product_country_field">';
woocommerce_wp_select(
array(
'id' => '_country_origin',
'label' => __('Country of origin', 'woocommerce'),
'options' => $options,
'desc_tip' => 'true'
)
);
echo '</div>';
}
// save fields
add_action('woocommerce_process_product_meta', 'woocommerce_product_country_fields_save');
function woocommerce_product_country_fields_save($post_id)
{
$woocommerce_country_origin = $_POST['_country_origin'];
if (!empty($woocommerce_country_origin))
update_post_meta($post_id, '_country_origin', esc_attr($woocommerce_country_origin));
}
Sort by Custom Field in Front-End
// sort field
function custom_add_country_ordering_args( $sort_args ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
switch( $orderby_value ) {
case '_country_origin':
$sort_args['orderby'] = 'meta_value';
$sort_args['order'] = 'asc';
$sort_args['meta_key'] = '_country_origin';
break;
case '_country_origin-desc':
$sort_args['orderby'] = 'meta_value';
$sort_args['order'] = 'desc';
$sort_args['meta_key'] = '_country_origin';
break;
}
return $sort_args;
}
add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_add_country_ordering_args' );
//change sort dropdown
function custom_add_country_orderby( $sortby ) {
//remove default sorting
unset($sortby["popularity"]);
unset($sortby["rating"]);
unset($sortby["date"]);
unset($sortby["price"]);
unset($sortby["price-desc"]);
$sortby['_country_origin'] = __( 'Sort by Country of origin', 'woocommerce' );
$sortby['_country_origin-desc'] = __( 'Sort by Country of origin descending', 'woocommerce' );
return $sortby;
}
add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_add_country_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_add_country_orderby' );
Please note that the products which has 'Country of origin' will only be displayed while sorting.
Filter by Custom Field in Front-End
Add this if you want filter rather than sort.
//add custom filter
add_action( 'woocommerce_before_shop_loop', 'filter_loop_start' );
function filter_loop_start( $query ){
$countries_obj = new WC_Countries();
$options = $countries_obj->__get('countries');
?>
<form name="product_filter_form" class="woocommerce-filtering" method="get">
<select name="country_origin" class="filterby" onChange="document.product_filter_form.submit();">
<option value="">Filter by Country of origin</option>
<?php foreach ($options as $key => $value) { ?>
<option value="<?php echo $key; ?>"<?php if($_GET['country_origin']==$key) echo ' selected'; ?>><?php echo $value; ?></option>
<?php } ?>
</select>
<input name="paged" value="1" type="hidden">
</form>
<?php
}
//modify query for filter
add_filter( 'pre_get_posts', 'my_modify_main_query' );
function my_modify_main_query( $query ) {
if( ! isset( $_GET['country_origin'] ) ) return $query;
$meta_query_args = array(
'meta_query' => array(
array(
'key' => '_country_origin',
'value' => sanitize_text_field( $_GET['country_origin'] ),
'compare' => 'LIKE',
)
)
);
$query->set('meta_query', $meta_query_args);
return $query;
}
I have a programming exercise and I wanted to check if what I have done so far is the best way to update a post title based on setting the query string. In my example below I create a link for updating the post and validate the origin with a nonce. I used the template_redirect action as it only fires once where as the wp and parse_query actions seemed to fire multiple times. The GET request can come from a form submit or link click but I've only attached the link example but the code should work for both situations.
function update_post_title() {
global $wpdb;
$post_id = get_query_var( 'post_id', 0 );
$post_title = get_query_var( 'post_title', '' );
$post_nonce = get_query_var( 'update_post_title_nonce', '' );
if( ! empty( $post_title ) AND $post_id > 0 ) {
if ( ! wp_verify_nonce( $post_nonce, 'update_post_title_action' ) ) {
wp_die( 'Security check failed' );
}
$post_title = sanitize_text_field( $post_title );
//$post_slug = sanitize_title_with_dashes( $post_title );
$post_id = intval( $post_id );
$rows_affected = $wpdb->update(
$wpdb->posts,
array( 'post_title' => $post_title ),
array( 'ID' => $post_id ),
array( '%s'),
array( '%d' )
);
}
}
function add_custom_query_vars( $public_query_vars ) {
$public_query_vars[] = 'post_id';
$public_query_vars[] = 'post_title';
$public_query_vars[] = 'update_post_title_nonce';
return $public_query_vars;
}
add_filter( 'query_vars', 'add_custom_query_vars' );
add_action( 'template_redirect', 'update_post_title' );
Sample link generate.
global $post;
<a href="<?php echo wp_nonce_url( add_query_arg( array(
'post_id' => 123,
'post_title' => 'The New Title', ),
site_url( $post->post_name ) ),
'update_post_title_action',
'update_post_title_nonce' );
?>">Click To Update</a>
I've been looking everywhere, but I just can't find it.
I'd like to give users a way to ask for a refund, but in order to do this, they need to provide a mandatory order number. Ideally, this would be in a tab in the My Account page, but it could also be a simple shortcode dropped into a contact form 7 form.
I just can't find any solution, anywhere.
I did find one using Gravity Form, but I'd like to do it without a plugin.
Any help would be appreciated!
You need to modify and customize below code to load dynamic orders as your requirements:
Find here code snippet:
add_action( 'wpcf7_init', 'wpcf7_add_form_tag_orderno' );
function wpcf7_add_form_tag_orderno() {
wpcf7_add_form_tag( array( 'orderno', 'orderno*' ),
'wpcf7_orderno_form_tag_handler', array()
);
}
function wpcf7_orderno_form_tag_handler( $tag ) {
/* get all orders here*/
/*$customer_orders = wc_get_orders( array(
'limit' => -1,
'status' => array( 'wc-pending' )
));
// Iterating through each Order with pending status
foreach ( $customer_orders as $order ) {
$customer_orders = wc_get_orders( array(
'limit' => -1,
'status' => array( 'wc-pending' )
) );
// Iterating through each Order with pending status
foreach ( $customer_orders as $order ) {
// Going through each current customer order items
foreach($order->get_items() as $item_id => $item_values){
$product_id = $item_values['product_id']; // product ID
// Order Item meta data
$item_meta_data = wc_get_order_item_meta( $item_id );
// Some output
echo '<p>Line total for '.wc_get_order_item_meta( $item_id, '_line_total', true ).'</p><br>';
}
}*/
$options = '';
$options .= '<option>-- select order no ---</option>';
$options .= '<option value="1">Order #10001</option>';
$options .= '<option value="2">Order #10002</option>';
$options .= '<option value="3">Order #10003</option>';
/* use attributes */
$atts = array();
$atts['class'] = $tag->get_class_option( $class );
$atts['id'] = $tag->get_id_option();
$atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
$atts['name'] = $tag->name;
$atts = wpcf7_format_atts( $atts );
$html = sprintf(
'<span class="wpcf7-form-control-wrap %1$s">
<select name="orderno">%2$s</select></span>',
sanitize_html_class( $tag->name ), $options);
return $html;
}
Add this shortcode in your contact form 7
[orderno orderno]
I hope it will be useful for you!
Here's what I came up with, thanks a lot for the cue!
add_action( 'wpcf7_init', 'wpcf7_add_form_tag_orderno' );
function wpcf7_add_form_tag_orderno() {
wpcf7_add_form_tag( array( 'orderno', 'orderno*' ),
'wpcf7_orderno_form_tag_handler', array()
);
}
function wpcf7_orderno_form_tag_handler( $tag ) {
$customer_orders = get_posts( apply_filters( 'woocommerce_my_account_my_orders_query',
array(
'numberposts' => $order_count,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(),
'post_type' => wc_get_order_types( 'view-orders' ),
'post_status' => array_keys( wc_get_order_statuses() ),
) ) );
if ( $customer_orders ) {
$atts = array();
$atts['class'] = $tag->get_class_option( $class );
$atts['id'] = $tag->get_id_option();
$atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
$atts['name'] = $tag->name;
$atts = wpcf7_format_atts( $atts );
echo '<select name="orderno">';
echo '<option>'.__( "Numéro de la commande", "sinope" ).'</option>';
foreach ( $customer_orders as $customer_order ) {
$order = wc_get_order( $customer_order );
$item_count = $order->get_item_count();
echo '
<option value="'.$order->get_order_number().'">
'.$order->get_order_number().'
</option>
';
}
echo '</select>';
}
}