Expand woocommerce single product page functionality with html - woocommerce

I know it's possible to add checkboxes and other via html to a woocommerce single product description / brief description of product (done that). Is it possible / what are the hooks, in order to save given customer selections and pass the information on to the cart? Customers are able to make choices but unfortunately no information is passed on by woocommerce.
thanks

Yes you may add your own HTML and then can use these data to the cart, these hints can be useful for you.
You may use an action
"add_filter( 'woocommerce_add_cart_item_data', 'Your_own_function', 10, 2);"
function Your_own_function($cart_data,$pro_id){
if(isset($_POST['your_checkbox_value'])){
$item_meta['your_meta_key'] = $_POST['your_checkbox_value'];
$cart_data ['product_meta'] = array('meta_data' => $item_meta);
}
return $cart_data;
}
and then you may retrieve these cart item data by using
"add_filter( 'woocommerce_get_item_data', "custom_get_item_data", 10, 2 );"
function custom_get_item_data($item_meta, $existing_item_meta){
foreach ($existing_item_meta['product_meta'] ['meta_data'] as $key => $val )
{
if($key == 'your_meta_key'){
$item_meta [] = array (
'name' => __('Custom Name','Text Domain'),
'value' => stripslashes( $val ),
);
}
}
return $item_meta;
}

Related

WordPress - Gravity Forms - Create field dynamically

Trying to create new fields for my form dynamically, as I'm getting json from 3rd party API. Based on this json, I need a number of fields added to my form - not fixed number. So, I'm doing this, hooking it onto gform_pre_render:
add_filter( 'gform_pre_process', 'create_products_gforms' );
add_filter( 'gform_admin_pre_render', 'create_products_gforms' );
add_filter( 'gform_pre_render', 'create_products_gforms' );
function create_products_gforms( $form ) {
$helper = new NSHelper();
$state_name = $_POST['input_7'] ?? '';
$code_value = $helper->get_state_code_by_name( $state_name );
// Only fetch products if current form id is 33, state code is defined
// and if there are products for this state.
if ( $form['id'] != 33 || !$code_value ) {
return $form;
}
// Get product list from NetSuit API based on state code
$products_json_data = get_products_data( $code_value );
$products = json_decode( json_decode( $products_json_data ) );
$new_field_id = 0;
foreach( $form['fields'] as $field ) {
if( $field->id > $new_field_id ) {
$new_field_id = $field->id;
}
}
$new_field_id++;
foreach ( $products as $product_object ) {
// Prepare field properties
$props = array(
'id' => $new_field_id,
'type' => 'singleproduct',
'label' => $product_object->onlinedisplayname,
'basePrice' => floatval( $product_object->price ),
'enableCalculation' => true
);
// Create new gravity forms field and add it to the form object
$nf = GF_Fields::create( $props );
// Hack - insert into array at specific position
// Needed to display product fields before other fields
// in the form
array_splice( $form['fields'], 11, 0, array($nf) );
$new_field_id++;
}
GFAPI::update_form( $form );
$form['dynamic_fields_ids'] = $added_fields_ids;
return $form;
}
This works, ie, it shows fields properly on the frontend. Now, the issue with this is that, once form is submitted, all the fields except these dynamically added ones are in the submission. But these are not. I assumed this has to do that these fields aren't registered in the form, so I also tried GFAPI::update_form( $form );, but that didn't help with submission part, though it udpates my form with new fields in the backend too.
Any ideas?
Based on your use-case, Milos, I would suggest using the gform_form_post_get_meta filter:
https://docs.gravityforms.com/gform_form_post_get_meta/
This will fire every time the form is fetched from the database and the most sure-fire way of guaranteeing your fields will be present.
If you prefer to be more surgical and stick with the gform_pre_render approach, you'll want to apply the same function on a couple other filters:
gform_pre_process
gform_admin_pre_render

WooCommerce- Order Details Thank You page Add Random Number for each product?

I am stuck on one problem, for my E-commerce website after placing order on i want to show random number for each product in order details section.
I have tried this : in theme(function.php)
add_action( 'woocommerce_order_status_processing', 'add_unique_id');
then
function add_unique_id($order_id) {
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ($items as $item_id => $product )
{
$gen_id ="Hi Dad!";
wc_add_order_item_meta($item_id, 'unique_id', $gen_id);
}
But by using this i am not getting unique number for each product.
I want to add random number in below red portion in image of Thank You page.
please help to resolve.
thanks in advance
If you have already done with the adding item_meta_data into the cart, hopefully, you can easily make it visible into cart too?
It is not that necessary but just for the testing purpose.
For this, you can use "woocommerce_get_item_data"
add_filter( 'woocommerce_get_item_data', 'mwb_wgm_woocommerce_get_item_data', 10, 2 );
function mwb_wgm_woocommerce_get_item_data($item_meta, $existing_item_meta){
//by using $existing_item_meta , find your unique_key (whether it is displaying or not)
foreach ($existing_item_meta as $key => $val ) {
if($key == 'unique_key') {
$item_meta [] = array (
'name' => __('RANDOM KEY','your_slug'),
'value' => stripslashes( $val ),
);
}
}
return $item_meta;
}
Let me know is your UNIQUE KEY is displaying there or not?
There are the various issue can be there
1. wc_add_order_item_meta (Woo version < 3.0.0)
If you're thinking to add item_meta to each of your product and then yes it will get displayed automatically on Thank You Order Page.
Please use "$item->add_meta_data('Your_Key',$order_val);" [WC_version >= 3.0.0]
Please make sure you've already set that "key" to your cart_item_meta by using this hook -> "woocommerce_add_cart_item_data".
Hope this may help you :)

Wordpress - Include data from new column in the search query

I added a new column to Woocommerce orders's screen, that indicates who is the order's creator (in that site, service representatives have the ability to create order for customer's in the backend).The problem is that when I search for that data in the orders screen, I can't find any.
The order's creator is set to the order with add_post_meta()
So I tried something like this:
function include_search( $query ) {
if ( is_admin() && $query->is_search() && $query->query['post_type'] == 'shop_order' ) {
$query->set( 'meta_query', array('key' => 'representative', 'value' => $query->query['s'], 'compare' => '=') );
}
}
add_action( 'pre_get_posts', 'include_search' );
But it doesn't work.
For example, If an order created by "Ben X", then I can see his name appears in the right column in the orders screen, but if I search for "Ben X" in the search box, I don't find that order.
Any help with that?
Thanks!
If anyone need help with that, I found the answer:
function filter_woocommerce_shop_order_search_fields( $array ) {
$array[] = 'representative'; //The order meta key that needs to be include in the search
return $array;
};
add_filter( 'woocommerce_shop_order_search_fields', 'filter_woocommerce_shop_order_search_fields', 10, 1 );

Woocommerce remove admin order item item meta

Im adding a custom item meta to every item with woocommerce_add_order_item_meta action.
I dont need to show this custom meta in the Order Detail, because it's an arry stringy that im using to print a pdf.
How can i remove this meta custom item? Is there some action to do it?
Thanks
I understand its a bit old question but I am answering for some other users who will have same issue in future.
If you want your order item meta to not display in admin order details page than you should append underscore (_) at the start of your meta name.
Example:
_custom_order_meta
The underscore trick no longer works. In Woo 3.x there is a hidden meta array:
add_filter('woocommerce_hidden_order_itemmeta',
array($this, 'hidden_order_itemmeta'), 50);
function hidden_order_itemmeta($args) {
$args[] = 'my_hidden_meta';
return $args;
}
It sounds like you need to keep it in order to print the PDF. If you override the order-details.php template you can possibly change:
$item_meta = new WC_Order_Item_Meta( $item['item_meta'], $_product );
to
$array = $item['item_meta'];
if( isset( $array['your_pdf_array_key'] ) ){ unset( $array['your_pdf_array_key'] ); }
$item_meta = new WC_Order_Item_Meta( $array, $_product );
EDIT
The wc_add_order_item_meta() function has 4 parameters as seen in the code:
function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
return add_metadata( 'order_item', $item_id, $meta_key, $meta_value, $unique );
}
If you choose a $meta_key with a preceding underscore, the meta will be automatically hidden from view on the checkout/order-received page, the My Order's list of the My account area, as well as in the admin's order overview page.
Therefore, I would suggest making your woocommerce_add_order_item_meta callback function look something like the following:
add_action( 'woocommerce_add_order_item_meta', '25979024_add_order_item_meta', 10, 3 );
function 25979024_add_order_item_meta( $order_item_id, $cart_item, $cart_item_key ) {
wc_add_order_item_meta( $order_item_id, '_pdf_something', 'hide this stuff' );
}

Woocommerce - Product price depending on country

I have 2 questions regarding Woocommerce for Wordpress.
I'm working on a site that sells speakers to the Danish market.
Question one:
Can I detect the IP of a visitor and detect which country the person is from? I guess this can be done with some ClientLocation api.
Can I then disable all shopping relatet pages and buttons if a person is not from Denmark. Fx: hiding the add to cart, cart and checkout.
I still want the persons to be able to see the prices, they should just not have the option to buy them.
Question 2:
Lets say that question one was sucessfull made. Then I would like to show different prices for other contries than Denmark. So if you are visiting the site from one country, the price is XXX and from another country the price is XXXX.
Let's say:
In USA the price is = $500
And in UK the price = £400
(This has nothing to do with currency. The market price is just different in different countries.)
I've looked at this plugin: http://wordpress.org/plugins/woocomerce-price-by-country/
It allowed me to write different prices for each product, but when I testet it with http://geopeeker.com/ I hadn't worked at all.
Can you give me some pointets or some links to some plugins that you know of?
UPDATE
I managed to solve question 1. I store the visitors country in a cookie with IP location XML API And then I could just create an if statement, saying that if the country was not equal to Denmark, then the add to cart, cart etc. should be removed.
So yeah, I would really appreciate it if anyknow could give me an idea on how I can solve question 2.
I'm able to detect country, but not able to specify a price of each product to the given country.
2'nd update:
Just to let any interested readers know, I ended up buying this plugin. which is working perfectly!
For the 2nd part of your question: If you are only using simple product types (without variations) then you can add custom price fields to the product data page and filter the price using woocommerce_get_price_html.
add_filter('woocommerce_get_price_html','so24863612_custom_price');
function so24863612_custom_price(){
global $post;
$_postID = $post->ID;
$product = get_product( $_postID );
$UK_price = get_post_meta($_postID, '_UK_price', true); //loads custom meta data
$return_price = $product->get_regular_price(); //default to regular price
if (!empty($UK_price)) {
$return_price = $UK_price;
}
return $return_price;
}
You can create and save custom fields on the product page like this:
//Display custom fields on product data page in admin
add_action( 'woocommerce_product_options_general_product_data', 'so24963039_display_custom_general_tab_fields' );
function so24963039_display_custom_general_tab_fields() {
global $woocommerce, $post;
$UK_price = get_post_meta( $post->ID, '_UK_price', true );
woocommerce_wp_text_input(
array(
'id' => '_UK_price',
'label' => __( 'UK Price (£)', 'woocommerce' ),
'value' => $UK_price,
'desc_tip' => 'false'
)
);
}
//Save custom fields to access via get_post_meta
add_action( 'woocommerce_process_product_meta', 'so24963039_save_custom_general_tab_fields' );
function so24963039_save_custom_general_tab_fields ($post_id) {
$woocommerce_UK_price = $_POST['_UK_price'];
if( !empty( $woocommerce_UK_price ) )
update_post_meta( $post_id, '_UK_price', esc_attr( $woocommerce_UK_price ) );
}
-----------------For products with Variations----------------------------
WARNING: Variable products are much more complicated and I'm not nearly as confident in this answer as I am with the simple products part above, but here's my current understanding either way. I had some mini-cart display issues that I had to hack around when using this method (which I will explain at the end), but the totals are calculated correctly in both the mini-cart and the regular cart.
First we want to add new fields to each variant on the variation tab of existing products:
add_action( 'woocommerce_product_after_variable_attributes', 'so24963039_variable_fields', 10, 2 ); //Display Fields
function so24963039_variable_fields( $loop, $variation_data ) {
echo '<tr><td>';
woocommerce_wp_text_input(
array(
'id' => '_variant_UK_price['.$loop.']',
'label' => __( 'UK Price (£)', 'woocommerce' ),
'desc_tip' => 'false',
'value' => $variation_data['_variant_UK_price'][0]
)
);
echo '</td></tr>';
}
We also need to add them dynamically whenever the user adds new variants on the edit product page:
add_action( 'woocommerce_product_after_variable_attributes_js', 'so24963039_variable_fields_js' ); //JS to add fields for dynamically added new variations
function so24963039_variable_fields_js(){ //add fields to new variations that get added
echo '<tr><td>';
woocommerce_wp_text_input(
array(
'id' => '_variant_UK_price[ + loop + ]',
'label' => __( 'UK Price (£)', 'woocommerce' ),
'desc_tip' => 'false',
'value' => $variation_data['_variant_UK_price'][0]
)
);
echo '</td></tr>';
}
Then we save changes to the custom fields in the variation meta data:
add_action( 'woocommerce_process_product_meta_variable', 'so24963039_save_variable_fields', 10, 1 ); //Save variation fields
function so24963039_save_variable_fields( $post_id ) {
if (isset( $_POST['variable_sku'] ) ) {
$variable_sku = $_POST['variable_sku'];
$variable_post_id = $_POST['variable_post_id'];
// Variant Tier 1 Price
$_variant_UK_price = $_POST['_variant_UK_price'];
for ( $i = 0; $i < sizeof( $variable_sku ); $i++) {
$variation_id = (int) $variable_post_id[$i];
if ( isset( $_variant_UK_price[$i] ) ) {
update_post_meta( $variation_id, '_variant_UK_price', stripslashes($_variant_UK_price[$i] ) );
}
}
}
}
Now that we have our custom variation meta data, we can access it in the custom price module like so:
add_filter('woocommerce_get_price_html','so24863612_custom_price');
function so24863612_custom_price(){
global $post;
$_postID = $post->ID;
$product = get_product( $_postID );
$product_type = $product->product_type;
$UK_price = get_post_meta($_postID, '_UK_price', true); //covers simple products
if($product_type == 'variation'){ //override with variant prices
$UK_price = get_post_meta($_postID, '_variant_$UK_price', true);
}
$return_price = $product->get_regular_price(); //default to regular price
if (!empty($UK_price)) {
$return_price = $UK_price;
}
return $return_price;
}
Now, I believe that part should have everything working except for the mini-cart display. For some reason it seems like I just couldn't figure out how to get access to the variation meta data to force it to display properly in the mini cart - like I found where the mini-cart display was being generated but I was having trouble getting the right context path to access the custom variable so I ended up having to do that in the template-tags.php and pass an array of custom values to an optional parameter in my custom price function. This feels very 'wrong' in terms of how we should do things, but it gets the job done. I'm very open to hearing the 'correct' solution to this part of the problem.
In template-tags.php:
<div class="small-7 large-7 columns"><?php
$product_title = $_product->get_title();
echo '<a class="cart_list_product_title" href="'.get_permalink($cart_item['product_id']).'">' . apply_filters('woocommerce_cart_widget_product_title', $product_title, $_product) . '</a>';
echo '<div class="cart_list_product_price">';
//original line: echo woocommerce_price($_product->get_price());
/*Custom Price Override Block*/
$_productID = $_product->id;
$product_type = $_product->product_type;
if($product_type == 'variation') {
$custom_field_data = $_product->product_custom_fields;
$regular_price = $custom_field_data['_regular_price'];
$custom_UK_price = $custom_field_data['_variant_UK_price'];
$custom_variant_prices = [$regular_price[0], $custom_UK_price[0]];
echo so24863612_get_custom_price($_productID, $custom_variant_prices );
} else {
echo so24863612_get_custom_price($_productID );
}
/*End Custom Price Override Block*/
echo ' /</div>';
echo '<div class="cart_list_product_quantity">'.__('Quantity', 'woocommerce').': '.$cart_item['quantity'].'</div>';
?></div>
I see your update that you did manage to get the visitor's country and that you can use this to create the if statement to remove the cart. (which is freaking cool, by the way)
Doesn't that answer your question 2, about changing the prices for each visitor? All you have to do is make sure that both prices are stored somewhere, and then just have it echo the Denmark or the UK one.
Prices are specific - custom fields
You mentioned this is NOT currency conversion - so you need to store both values. Add a custom field to the product entry that you edit with that new price, and name it "denmarkprice" or something
I'm not 100% familiar enough with WooCommerce to say what custom field plugin might work, but you could use http://www.advancedcustomfields.com/ if you don't want to just create the custom field yourself and call the variable with the_meta() when you want to display it inside your if else statement.
http://codex.wordpress.org/Custom_Fields

Resources