Is it possible to make a user-generated temporary product to be added to cart in WooCommerce?
I'm trying to transfer a non-wordpress website to WordPress, but the site already has a sophisticated e-commerce system that the client doesn't want to change. What basically happens is a visitor specifies the measurement of the product that the client is selling, add different variations to it, and then after submitting, the website generates the product's price based on the visitor's input.
Adding products will be very tedious because they have too many products with thousands of variations. So our solution is this.
I'm open to other plugin suggestions aside from WooCommerce. I already tried using Gravity Forms, but I got stuck in the end because our client's current website has to be an e-commerce site after it was added to the cart.
This is solved!
Here is what I did just in case someone needs help with this in the future.
First I made a page with a form. Action is whichever the page will live in and method is post.
<form method="post" action="/order-page">
<label for="tc_name" title="Full Name">Full Name</label>
<input type="text" name="tc_name"/>
<label for="tc_title" title="Product Name">Product Name</label>
<input type="text" name="tc_title">
<label for="tc_description" title="Product Description">Product Description</label>
<textarea name="tc_description"></textarea>
<label for="tc_price" title="Price">Price</label>
<input type="number" name="tc_price"/>
<input type="submit" value="Submit"/>
</form>
Then on the next page, I grabbed the values, created the product based on the values given, and then added a shortcode to display the cart button.
if('POST' == $_SERVER['REQUEST_METHOD'] && !empty($_POST['tc_price'])) {
//grab the values
$pName = $_POST["tc_name"];
$pDescription = $_POST["tc_description"];
$pPrice = $_POST["tc_price"];
$post_title = $_POST["tc_title"];
//add them in an array
$post = array(
'post_author' => $pName,
'post_content' => $pDescription,
'post_status' => "publish",
'post_title' => $post_title,
'post_type' => "product",
);
//create product
$product_id = wp_insert_post( $post, __('Cannot create product', 'bones') );
//type of product
wp_set_object_terms($product_id, 'simple', 'product_type');
//add price to the product, this is where you can add some descriptions such as sku's and measurements
update_post_meta( $product_id, '_regular_price', $pPrice );
update_post_meta( $product_id, '_sale_price', $pPrice );
update_post_meta( $product_id, '_price', $pPrice );
//get woocommerce shortcode for add to cart
$myButton = do_shortcode('[add_to_cart id="' . $product_id . '"]');
//display product
echo $myButton;
}
and then lastly, once an order is completed, delete the product by hooking an action to woocommerce_thankyou. I put it in the functions.
function mysite_completed($order_id) {
//get order ID
$order = new WC_Order( $order_id );
//grab items from the order id
$items = $order->get_items();
//loop thru all products in the order section and get product ID
foreach ( $items as $item ) {
$product_id = $item['product_id'];
//choose whatever suites you, trash the product is what I picked
//permanently deletes product
//wp_delete_post($product_id);
//trashes post
wp_trash_post($product_id);
}
}
To Extend this topic and trash or delete products from a category when the order is successfully created.
First you need to create a custom category where all the products you'd like to trash or delete upon successful order creation will live. Then add the following code;
function delete_product_on_woocommerce_complete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
// 1. Get order object
$order = wc_get_order( $order_id );
// 2. Initialize $cat_in_order variable
$cat_in_order = false;
foreach ( $items as $item ) {
$product_id = $item['product_id'];
if ( has_term( 'machine', 'product_cat', $product_id ) ) { //Where machine is the custom product category slug
// 3. choose whatever suites you, delete the product is what I picked
//To Delete Product
wp_delete_post($product_id);
//To Trash Product
//wp_trash_post($product_id);
}
}
}
add_action( 'woocommerce_thankyou', 'delete_product_on_woocommerce_complete_order', 5 );
Code goes in function.php file of your active child theme (or active theme) or cutsom plugin. Tested and worked.
Related
I would like to create a product in WooCommerce that is sold in units of gram.
The customer would enter the number of grams they want (in an input field) on the product page, and the price would be computed on the fly and added to the cart.
My question is: is this possible, and if so, can someone give me just a "big picture" idea of how I would implement it?
I don't need line-by-line code, just hoping someone with more knowledge of the structure of Woo can guide me on how to best attack the problem.
I already have parts of it worked out:
I can decide that the price entered for the product is the price per
100 grams, so that is how the seller will enter the price.
Then I can
write a little bit of Javascript to compute the price on the fly and
display it on the page as the user types the amount they want. No
problem.
But... I think every discrete product in Woo needs to have its own price.. So for example, if a customer wants 123g of a product, it seems like I might have to create a variation on the fly for that specific price/amount, and then add that to the cart. Which (judging by this) looks non-trivial and a little hacky. Is there a better way to do this?
WooCommerce has an option to show the weights as grams.
The following code will display the KG weights as grams on the WooCommerce templates :
// Convert the product weight
function ag_woocommerce_product_get_weight( $weight ) {
// Only convert if we have a weight
if ($weight) {
// The weight is in KGS, and we want grams, to multiple by 1000
$weight = $weight * 1000;
}
return $weight;
};
// add the filter
add_filter( 'woocommerce_product_get_weight', 'ag_woocommerce_product_get_weight', 10, 1 );
Hope this might help. Cheers!
There is a free plugin for WooCommerce that allows you to input a unit of measure (UOM) for each product:
https://wordpress.org/plugins/woocommerce-unit-of-measure/
I found this plugin that does pretty much exactly what I need-- https://woocommerce.com/products/measurement-price-calculator/
It's easier and quicker to give you that real example, than explain step by step… You will see which hooks are used for all steps or tasks.
You dont need variable products or generate a variation on the fly.
You just need to set on each simple product the price for one gram (or any other base). Now in this code, you can target those products with:
an array of product Ids
or by product categories (or even product tags).
Your concern is about the way to pass the data in the cart, to update the final price for each product and display the chosen grams amount in cart, checkout and in the order.
So in each product you will only set the price by gram… (or you can also make changes in the code and set the product price for 100 grs or even any other base).
The code:
// Add a product custom field "grams_quantity" that will update the displayed price
add_action('woocommerce_before_add_to_cart_button', 'special_product_by_grams', 25);
function special_product_by_grams(){
global $product;
// HERE Define the special product IDs sold by grams
$targeted_product_ids = array(37);
// or HERE Define a product categories (ids, slugs or names)
$categories = array('sold-by-gram');
// Only for products sold by gram
$product_id = $product->get_id();
if ( ! ( in_array( $product_id, $targeted_product_ids ) || has_term( $categories, 'product_cat', $product_id ) ) ) return;
?>
<div class="grams-field">
<label for="grams_quantity"><?php _e('Grams: ','woocoomerce'); ?><span></span><br>
<input type="number" step="1" name="grams_quantity" class="grams_quantity" id="grams_quantity" value="1">
</label>
</div><br>
<script type="text/javascript">
(function($){
// variables initialization
var priceByGram = <?php echo wc_get_price_to_display( $product ); ?>,
currencySymbol = $(".woocommerce-Price-currencySymbol").html(),
updatedPrice;
// On live event: imput number fields
$('input#grams_quantity').on( "click blur", function(){
updatedPrice = ($(this).val() * priceByGram).toFixed(2);
$(".woocommerce-Price-amount.amount").html('<span class="woocommerce-Price-amount amount">'+updatedPrice+' '+currencySymbol+'</span>');
console.log("event"); // <== To be removed
});
})(jQuery);
</script>
<?php
}
// Save the "grams_quantity" custom product field data in Cart item
add_filter( 'woocommerce_add_cart_item_data', 'save_in_cart_the_custom_product_field', 10, 2 );
function save_in_cart_the_custom_product_field( $cart_item_data, $product_id ) {
if( isset( $_POST['grams_quantity'] ) ) {
$cart_item_data[ 'grams_quantity' ] = $_POST['grams_quantity'];
// When add to cart action make an unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $_POST['grams_quantity'] );
}
return $cart_item_data;
}
// Update product price by grams in cart and checkout
add_filter( 'woocommerce_before_calculate_totals', 'update_prices_by_gram', 10, 1 );
function update_prices_by_gram( $cart_object ) {
// HERE Define the special product IDs sold by grams
$targeted_product_ids = array(37);
// or HERE Define a product categories (ids, slugs or names)
$categories = array('sold-by-gram');
foreach ( $cart_object->get_cart() as $cart_item ) {
// Only for products sold by gram
$product_id = $cart_item['product_id'];
if ( in_array( $product_id, $targeted_product_ids ) || has_term( $categories, 'product_cat', $product_id ) ){
// Get an instance of the WC_Product object and the
$product = $cart_item['data'];
$grams = $cart_item['grams_quantity'];
// Method is_on_sale() manage everything (dates…)
$product->set_price( $product->get_price() * $grams);
}
}
}
// Render "grams_quantity" the custom product field in cart and checkout
add_filter( 'woocommerce_get_item_data', 'render_product_custom_field_meta_on_cart_and_checkout', 10, 2 );
function render_product_custom_field_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
$custom_items = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( isset( $cart_item['grams_quantity'] ) )
$custom_items[] = array(
'name' => __( 'Grams', 'woocommerce' ),
'value' => sanitize_text_field( $cart_item['grams_quantity'] ),
'display' => sanitize_text_field( $cart_item['grams_quantity'] ),
);
return $custom_items;
}
// Save "grams_quantity" to the order items meta data
add_action('woocommerce_add_order_item_meta','add_product_custom_fiel_to_order_item_meta', 1, 3 );
function add_product_custom_fiel_to_order_item_meta( $item_id, $item_values, $item_key ) {
if( isset( $item_values['grams_quantity'] ) )
wc_update_order_item_meta( $item_id, 'Grams', sanitize_text_field( $item_values['grams_quantity'] ) );
}
Code goes in function.php file of your active child theme (or active theme) or in any plugin file.
Tested and works.
Using Poor Guys Swiss Knife plugin for WooCommerce, I created 3 new Billing fields: birthday (date), newsletter (select: yes/no) and terms & conditions (select: yes/no). I successfully registered as a new customer on the site and filled these new fields.
However when checking the account thus created in the dashboard, I see all the regular fields except the 3 ones I created with the Poor Guys Swiss Knife plugin. Why is that ?
Clearly plugin is not sending fields data to user account.
You can achieve same results using woocommerce custom fields in your functions.php file.
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_phone'] = array(
'label' => __('Phone', 'woocommerce'),
'placeholder' => _x('Phone', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
To make it required use this code:
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['my_field_name'] )
wc_add_notice( __( 'Please enter something into this new shiny field.' ), 'error' );
}
you can find more on this website:
http://docs.woothemes.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
Here is a solution that I came up with and it has been working fine for me, hope it helps you as well.
I created a few new fields for the billing form using that plugin but let's just use one as an example:
-Resale License # ( billing_resale_license_ )
Now, the plugin ( or the code from the first answer ) will add the field to the form for you, in my case, I end up with:
<input type="text" class="input-text " name="billing_resale_license_" id="billing_resale_license_" placeholder="" value="" display="text">
Now, we need to save the value of that field to the user_meta table, like so:
add_action( 'woocommerce_checkout_process', 'ws_billing_fields_save', 10, 1 );
function ws_billing_fields_save( $user_id ){
if ( isset( $_POST['billing_resale_license_'] ) ) {
update_user_meta($user_id, 'billing_resale_license_', $_POST['billing_resale_license_']);
}
}
Now that data is stored in user_meta, we need to hook in to the profile area to display it and allow it to be edited by the user or admins.
add_action( 'show_user_profile', 'ws_update_user_profile' );
add_action( 'edit_user_profile', 'ws_update_user_profile' );
function ws_update_user_profile( $user ){ ?>
<h3>Additional Fields</h3>
<table class="form-table">
<tr>
<th><label for="billing_resale_license_">Resale #</label></th>
<td><input type="text" name="billing_resale_license_" value="<?php echo esc_attr(get_the_author_meta( 'billing_resale_license_', $user->ID )); ?>" class="regular-text" /></td>
</tr>
</table>
add_action( 'personal_options_update', 'save_extra_fields' );
add_action( 'edit_user_profile_update', 'save_extra_fields' );
function save_extra_fields( $user_id ){
update_user_meta( $user_id,'billing_resale_license_', sanitize_text_field( $_POST['billing_resale_license_'] ) );
}
I chose to break my additional fields into their own table just above the default Woocommerce fields as I have many of them and they are more specific to the user rather than the order processing itself, so I keep them organized in their own table titled "Additional Fields".
I think the billing fields are visible on the order only, not the user. User fields are available through the register_form and user_register hooks.
I was wondering if it was possible to make the coupon field mandatory on WooCommerce.
I know that this is possible using functions, however this is slightly above my current skill level so I was wondering if you could give me a step-by-step version of how to accomplish this. Any answer would be much appreciated.
I don't know about the function but you can modify the plugin to achieve this in following manner :
Make one folder in your theme folder woocommerce and in new created woocommerce folder, create another folder with checkout name.
So now it will look something like wp-content > themes > your-theme > woocommerce > checkout.
Now go to your plugin directory and follow below path :
wp-content > plugins > woocommerce > templates > checkout
When you go in above path, you will find one file named as form-coupon.php. Copy that file and paste it to the directory which we created at top of that answer.
wp-content > themes > your-theme > woocommerce > checkout > form-coupon.php.
Now its time to modify the code in wp-content > themes > your-theme > woocommerce > checkout > form-coupon.php :
Find following code line in above mentioned file :
<input type="text" name="coupon_code" class="input-text" placeholder="<?php _e( 'Coupon code', 'woocommerce' ); ?>" id="coupon_code" value="" />
And replace above line with
<input type="text" name="coupon_code" class="input-text" placeholder="<?php _e( 'Coupon code', 'woocommerce' ); ?>" id="coupon_code" value="" required/>
Note: Here I have added required attribute of html.
Tell me if you have any doubt.
UPDATED:
add_action('woocommerce_check_cart_items', 'make_coupon_code');
function make_coupon_code()
{
global $woocommerce;
if(is_cart() || is_checkout()){
$my_coupon = $woocommerce->cart->applied_coupons;
echo $woocommerce->cart->get_applied_coupons;
if(empty($my_coupon))
{
$woocommerce->add_error("Please enter coupon code to checkout.");
}
}
}
Please give it a try and let me know feedback.
NOTE: UNTESTED
to solve the problem try this code:
<?php
add_action('woocommerce_check_cart_items', 'make_coupon_code');
function make_coupon_code()
{
global $woocommerce;
if(is_cart() || is_checkout()){
$my_coupon = $woocommerce->cart->applied_coupons;
echo $woocommerce->cart->get_applied_coupons;
if(empty($my_coupon))
{
wc_add_notice( '<strong>' . $btn['label'] . '</strong> ' . __( 'insert coupon code', 'woocommerce' ), 'error' );
}
}
}
?>
in functions.php instead of the one above...
for me it works
Add the following code in functions.php
Require Coupon for Single Product
add_action( 'woocommerce_check_cart_items', 'mandatory_coupon_for_specific_items' );
function mandatory_coupon_for_specific_items() {
$targeted_ids = array(37); // The targeted product ids (in this array)
$coupon_code = 'summer2'; // The required coupon code
$coupon_applied = in_array( strtolower($coupon_code), WC()->cart->get_applied_coupons() );
// Loop through cart items
foreach(WC()->cart->get_cart() as $cart_item ) {
// Check cart item for defined product Ids and applied coupon
if( in_array( $cart_item['product_id'], $targeted_ids ) && ! $coupon_applied ) {
wc_clear_notices(); // Clear all other notices
// Avoid checkout displaying an error notice
wc_add_notice( sprintf( 'The product"%s" requires a coupon for checkout.',
$cart_item['data']->get_name() ), 'error' );
break; // stop the loop
}
}
}
Replace 37 by the your product ID in $targeted_ids = array(37); you can have multiple product IDs like $targeted_ids = array(37,48,12);
Replace "summer2" by any other coupon code in $coupon_code = 'summer2';
Don't forget to add this coupon code in WooCommerce before using it.
Require coupon for all products
add_action( 'woocommerce_check_cart_items', 'mandatory_coupon_code' );
function mandatory_coupon_code() {
$product_categories = array( 'clothing' ); // Category ID or slug of targeted category
$coupon_code = 'summer2'; // The required coupon code
$coupon_applied = in_array( strtolower($coupon_code), WC()->cart->get_applied_coupons() );
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ){
if( has_term( $product_categories, 'product_cat', $cart_item['product_id'] ) && !$coupon_applied ) {
wc_clear_notices(); // Clear all other notices
// Avoid checkout displaying an error notice
wc_add_notice( sprintf( 'The product"%s" requires a coupon for checkout.',
$cart_item['data']->get_name() ), 'error' );
break; // stop the loop
}
}
}
Replace $product_categories = array( 'clothing' ); by any other category name or category ID.
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
I've been trying to add a single text input field to every item in the cart and submit that user input to product's meta info. It's been 2 days and I haven't succeeded yet.
My objective is to:
Take input from user for every item added to the cart.
Display that input in the order's meta info.
Display that input in confirmation email sent to the customer.
So far, I have copied the template file to my theme and added an input field inside a cell. I'm having trouble with the hooks, learned about hooks I will need from WooCommerce Product Gift Wrap plugin as indicated in this woocommerce issue.
Code I added to the cart.php template copied in my theme directory :
$input_url_data = '<div class="input-url"><input type="text" name="cart-url" value="" title="" class="input-text cart-url text" /></div>';
echo apply_filters( 'woocommerce_add_cart_item_data', $input_url_data, $cart_item_key );
Code I added to my theme's functions.php :
add_filter( 'woocommerce_add_cart_item_data','add_cart_item_data', 10, 2 );
add_filter( 'woocommerce_get_cart_item_from_session','get_cart_item_from_session', 10, 2 );
add_filter( 'woocommerce_get_item_data','get_item_data', 10, 2 );
add_filter( 'woocommerce_add_cart_item','add_cart_item', 10, 1 );
add_action( 'woocommerce_add_order_item_meta','add_order_item_meta', 10, 2 );
function add_cart_item_data( $cart_item_meta, $product_id ) {
$input_url_key = "";
$input_url_data['inputurl'] = $input_url_key;
return $input_url_data;
}
function get_cart_item_from_session( $cart_item, $values ) {
if ( ! empty( $values['inputurl'] ) ) {
$cart_item['inputurl'] = true;
}
return $cart_item;
}
function get_item_data( $item_data, $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) )
$item_data[] = array(
);
return $item_data;
}
function add_cart_item( $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) ) {
}
return $cart_item;
}
function add_order_item_meta( $item_id, $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) )
woocommerce_add_order_item_meta( $item_id, __( 'URL by buyer', 'custom_input_url' ), __( 'Yes', 'custom_input_url' ) );
}
Documentation about hook woocommerce_add_cart_item_data isn't very helpful and I'm stuck at this. How do I proceed?
There is a wordpress plugin called WC Fields Factory for the exact purpose.
You can also achieve this by using the following woocommerce hooks woocommerce_before_add_to_cart_button, woocommerce_add_to_cart, woocommerce_cart_item_name,and 'woocommerce_add_order_item_meta'
like for adding text field to product page
function add_name_on_tshirt_field() {
echo '<table class="variations" cellspacing="0">
<tbody>
<tr>
<td class="label"><label for="color">Name On T-Shirt</label></td>
<td class="value">
<input type="text" name="name-on-tshirt" value="" />
</td>
</tr>
</tbody>
</table>';
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_name_on_tshirt_field' );
For displaying custom field on cart item table use the below
function render_meta_on_cart_item( $title = null, $cart_item = null, $cart_item_key = null ) {
if( $cart_item_key && is_cart() ) {
echo $title. '<dl class="">
<dt class="">Name On T-Shirt : </dt>
<dd class=""><p>'. WC()->session->get( $cart_item_key.'_name_on_tshirt') .'</p></dd>
</dl>';
}else {
echo $title;
}
}
add_filter( 'woocommerce_cart_item_name', 'render_meta_on_cart_item', 1, 3 );
to make your custom meta data on you order details, do some thing like this
function tshirt_order_meta_handler( $item_id, $values, $cart_item_key ) {
wc_add_order_item_meta( $item_id, "name_on_tshirt", WC()->session->get( $cart_item_key.'_name_on_tshirt') );
}
add_action( 'woocommerce_add_order_item_meta', 'tshirt_order_meta_handler', 1, 3 );
for detailed implementation, i have an article about how to do this without using any plugins. http://sarkware.com/how-to-pass-custom-data-to-cart-line-item-in-woocommerce-without-using-plugins/
It's easy. Try searching and reading code of Woocommerce.
This much of code got me to point where I can add Url # Cart. And I can see it in Order review as customer and as admin.
I can't test email because I'm lazy. I'm sorry.
Something like this goes in templates\cart\cart.php (there is need for some more code as it's seperate column)
<td class="product-url">
<?php
$html = sprintf( '<div class="url"><input type="text" name="cart[%s][url]" value="%s" size="4" title="Url" class="input-text url text" /></div>', $cart_item_key, esc_attr( $values['url'] ) );
echo $html;
?>
</td>
Functions.php
// get from session your URL variable and add it to item
add_filter('woocommerce_get_cart_item_from_session', 'cart_item_from_session', 99, 3);
function cart_item_from_session( $data, $values, $key ) {
$data['url'] = isset( $values['url'] ) ? $values['url'] : '';
return $data;
}
// this one does the same as woocommerce_update_cart_action() in plugins\woocommerce\woocommerce-functions.php
// but with your URL variable
// this might not be the best way but it works
add_action( 'init', 'update_cart_action', 9);
function update_cart_action() {
global $woocommerce;
if ( ( ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && $woocommerce->verify_nonce('cart')) {
$cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
if ( isset( $cart_totals[ $cart_item_key ]['url'] ) ) {
$woocommerce->cart->cart_contents[ $cart_item_key ]['url'] = $cart_totals[ $cart_item_key ]['url'];
}
}
}
}
}
// this is in Order summary. It show Url variable under product name. Same place where Variations are shown.
add_filter( 'woocommerce_get_item_data', 'item_data', 10, 2 );
function item_data( $data, $cart_item ) {
if ( isset( $cart_item['url'] ) ) {
$data['url'] = array('name' => 'Url', 'value' => $cart_item['url']);
}
return $data;
}
// this adds Url as meta in Order for item
add_action ('woocommerce_add_order_item_meta', 'add_item_meta', 10, 2);
function add_item_meta( $item_id, $values ) {
woocommerce_add_order_item_meta( $item_id, 'Url', $values['url'] );
}
400$ is nice price.
You can do this fairly easily with the Woocommerce Product Add-ons plugin
From the WooThemes website:
Allow your customers to customise your products by adding new options
such as input boxes, dropdowns or checkboxes. With the Product Add-ons
extension, gift messages, donations, laser engraving and any other
product which may require user input in some way is now an option for
your customers!
Product add-ons supports required fields, textareas, checkboxes,
radios, select boxes, custom price inputs and file upload boxes.
I've used it before to add an additional donation field to a product purchase and display that on the thank you page/receipt email.
It's about $50 US and will get you up and running in no time to add the text input and display the field on thank you page/email like you want. $50 is definitely worth the amount of time you'd save drying to develop this feature yourself.
Here's the flow from the end-users perspective:
End user enters in field data and adds product to cart
When User views cart the data they entered into the custom field displays along with the product
After purchase, end user lands on thank you page and receives receipt email with field data included with the product item.
On the backend:
Create custom field for each product. The option is located on the Add-Ons menu tab.
Create a new Addon Group
Enter a group name (for easier organization)
Add a new option and enter the label (this is what the end user sees and is tied to the product)
Update/Publish product.
For completed orders, this is what you will see in the Order Details admin:
Hope this helps and saves you a ton of time in development!