Hide add to cart button in WooCommerce but show stock status - woocommerce

I want to hide the add to cart button in WooCommerce but still show the stock status message... It's easy in CSS but i am looking for a solution in php.
For now i've been using this code below but it hide all the shop functionnality, I just need to hide the add to cart button and show the out of stock message if the product is out of stock.
// Remove add to cart on single product pages
add_action( 'woocommerce_single_product_summary', 'hide_single_product_prices', 1 );
function hide_single_product_prices(){
global $product;
if ( has_term( array('category1', 'category2', 'category3', 'category4'), 'product_cat', $product->get_id() ) ) :
//Hide add-to-cart button, quantity buttons (and attributes dorpdowns for variable products)
if( ! $product->is_type('variable') ){
remove_action('woocommerce_single_product_summary','woocommerce_template_single_add_to_cart', 30 );
} else {
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
}
endif;
}```

So the issue is that when you remove the function 'woocommerce_template_single_add_to_cart' from 'woocommerce_single_product_summary' what you're actually doing is telling woocommerce not to load the template at all, located in: templates/single-product/add-to-cart. Which template loads there depends on the product type, but I'll assume simple for now.
If you look at that template, its not ACTUALLY just the add to cart button. It contains the call to wc_get_stock_html() that displays what you're looking for. So there isn't actually a good way just with removing a hook, to hide ONLY the button.
Instead what you'll have to do is one of two things: You can copy the add-to-cart/simple.php template into your theme, and edit it there with your logic. You'll likely want to wrap the button like this:
<?php if( ! your_custom_function( $product ) : ?>
<div class='buttons-container'>
<button type="submit" name="add-to-cart" value="<?php echo esc_attr( $product->get_id() ); ?>" class="single_add_to_cart_button btn btn--pink"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
</div>
<?php endif; ?>
The downside to that is that if you want this to work for all product types, you'd have to copy each template and do something similar.
So alternatively, what you could do is remove the action - as you have in your code above, and then Re-add the stock display wherever you'd like it. I would lean this direction for the reason above. Something like this:
remove_action( 'woocommerce_single_product_summary','woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_single_product_summary', function(){
global $product;
if( $product->is_purchasable() ){
echo wc_get_stock_html( $product );
}
}, 30 );

Related

Allow one cart item before place order button click or proceed to checkout button click

I want to disallow place order if cart item is more than two on click of proceed to checkout or Place Order button click in woocommerce.
I do not want to check it on add to cart validation check, please any one can guide me about it?
You can use WooCommerce Min/Max Quantities extension to set a minimum and maximum quantity required to checkout.
or
You can set custom code to your functions.php theme file by using "woocommerce_after_checkout_validation" filter and can use $posted array to check value and set validation,
add_action('woocommerce_after_checkout_validation', 'rei_after_checkout_validation');
function rei_after_checkout_validation( $posted ) {
// do all your logics here...
}
function custom_checkout_button_action(){
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$total = 0;
foreach($items as $item => $values) {
$total = $values['quantity'];
}
if($total>=2){
?>
<?php _e( 'Check On Out', 'woocommerce' ); ?>
<?php
}
else{
?>
<?php _e( 'Check On Out', 'woocommerce' ); ?>
<?php
}
}
add_action('woocommerce_proceed_to_checkout', 'custom_checkout_button_action');
If you are using butto you can change your HTML accordingly to disable button instead of link in above code on check out page before place an order page.

Woocommerce product images replaced with a gallery plugin

First I would like to analyze my problem. Using Wordpress/Woocommerce I need to add videos beside images in the gallery of the product. Woocommerce does not support videos at all.
So, I thought to install an extra gallery plugin that supports both images and videos.
Now, I want to map a specific image/video gallery collection to a specific product. I want also to view this gallery collection in a new region that is not belong to the standard text fields like description or short description. Lets say above of the main product image. The php code that represent the gallery collection id=1 looks like below :
<?php echo do_shortcode('[wonderplugin_gallery id="1"]'); ?>
The problem is that I need the gallery collection id to be variable, something like this :
<?php echo do_shortcode('[wonderplugin_gallery id="X"]'); ?>
where X represnt the specific gallery collection. How the heck can I connect the gallery collection ID XXXX to my Product page XXXXX?
I have programming skills but I am new to the wordpress code logic.
Any other suggestions to my problem like plugins that may replace the default product gallery with better one ?
Regards,
I'd either use the product custom fields as Anand suggested, or create a metabox with the necessary input fields (or dropdowns depending on how you use the gallery plugin).
First I'd create a metabox, and in that metabox I'd pull the info from the plugin (gallery id's and names). Out of that you can create a dropdown. You should be able to select the id from that metabox for each product like you suggested. For instance something like this could work:
<?php
if ( ! function_exists( 'product_add_meta' ) ){
function product_add_meta(){
add_meta_box("gallery_dropdown", "Select Gallery", "product_gallery_meta_box", "product");
}
}
add_action("admin_init", "product_add_meta");
if ( ! function_exists( 'product_gallery_meta_box' ) ){
function product_gallery_meta_box( $post ){
$post_types = array('product'); //limit meta box to certain post types
global $post;
$product = get_product( $post->ID );
$values = get_post_custom( $post->ID );
$gallery = (isset($values['gallery'][0])) ? $values['gallery'][0] : '';
wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' );
?>
<p>
<select name="gallery" id="gallery">
//example of how the option should look
<option value="<?php echo $gallery_id; ?>" <?php selected( $gallery, $gallery_id ); ?>><?php echo $gallery_name; ?></option>
<?php
//pull options from plugin here and create an option dropdown with foreach
?>
</select>
</p>
<?php
}
}
if ( ! function_exists( 'product_gallery_save_meta_box' ) ){
function product_gallery_save_meta_box( $post_id ){
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
return;
}
if( !isset( $_POST['gallery'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) {
return;
}
if( !current_user_can( 'edit_pages' ) ) {
return;
}
if( isset( $_POST['gallery'] ) ){
update_post_meta( $post_id, 'gallery', wp_kses( $_POST['gallery'] ,'') );
}
}
}
add_action( 'save_post', 'product_gallery_save_meta_box' );
If you put this in the functions.php, it should show a metabox called 'Select Gallery' with an empty dropdown on your woocommerce product page.
I haven't filled the options that you get from the plugin with which you create your galleries, but it shouldn't be too hard.
One way is to bind the product page id and gallery id. If you can change the id of a gallery then change it to match the id of the product page. Now you can create shortcode with any of these two examples.
// outside the loop use global ( uncomment appropriate statement )
// global $product;
// global $post;
do_shortcode( sprintf( '[wonderplugin_gallery id="%d"]', $product->id ) );
do_shortcode( sprintf( '[wonderplugin_gallery id="%d"]', $post->ID ) );
HERE is a link for plugin that reveals most of the IDs on admin pages.
Another is to create Custom Field ( post meta ) in edit product admin page ( named gallery_id for example ), and to save there id of the gallery to use. To create shortcode use get_post_meta() function that retrieves the saved post meta.
do_shortcode( sprintf( '[wonderplugin_gallery id="%d"]', get_post_meta( $post->ID, 'gallery_id', true ) ) );
To get the gallery id meta use $post->ID, $product->id, or get_the_ID() function, the latter only inside the loop.

Add meta box to categories admin panel in Wordpress

I'm working on a Wordpress theme and I need to add a meta box (checkbox) to the category admin panel.
I've written the code to add the meta box to the panel but there is 2 problems:
1- First it appears below the "Add category button"
2- What functions should I use to save the checkbox value in the database ?
and there is the code to add the checkbox
add_action ( 'category_add_form_fileds', 'add_to_main_page');
add_action('category_edit_form', 'add_to_main_page');
function add_to_main_page() {
?>
<input type="checkbox" name="add_to_main" id="add_to_main" value="1">
<label for="add_to_main">This category on main page</label>
<?php }
Thanks in advance
After fixing one typo—"category_add_form_fileds" to "category_add_form_fields"—your code worked fine for me. I get a checkbox on both forms above the "Add New Category" / "Update" buttons. This is a complete version and should do the trick:
add_action( 'category_add_form_fields', 'add_to_mainpg_fields' );
add_action( 'category_edit_form', 'add_to_mainpg_fields' );
function add_to_mainpg_fields() {
?>
<input type="checkbox" name="add_to_main" id="add_to_main" value="1" />
<label for="add_to_main">This category on main page</label>
<?php
}
add_action( 'created_category', 'add_to_mainpg_save' );
add_action( 'edited_category', 'add_to_mainpg_save' );
function add_to_mainpg_save( $term_id ) {
if( !isset( $_POST['add_to_main'] ) )
return;
$stickies = get_option( 'main_page_cats' );
if( !is_array( $stickies ) )
$stickies = array( $term_id );
if( !in_array( $term_id, $stickies ) )
$stickies[] = $term_id;
update_option( 'main_page_cats', $stickies );
}
This is a modified version of the stick_post function used for sticky posts.
This tutorial is instructive for saving multiple options. Two robust solutions are this plugin and this library. I understand if you don't want all that for a single field, but others might. :)

Display product variations on category page

How do I show all product variations on WooCommerce category pages?
I have set up a variable product with three variations. I want each variation (not the variable product itself) to be displayed as a separate product on the product category page. The user should be able to open a variable product and add it to the cart.
Is this possible?
Example : http://bennyhendrikx.be/product-categorie/clothing/page/2/
Add this code in youre functions.php
if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
function woocommerce_template_loop_add_to_cart() {
global $product;
if ($product->product_type == "variable" && (is_product() || is_product_category() || is_product_tag())) {
woocommerce_variable_add_to_cart();
}
else {
woocommerce_get_template( 'loop/add-to-cart.php' );
}
}
}
add_action('woocommerce_after_shop_loop_item_title','woocommerce_template_single_variation', 5);
function woocommerce_template_single_variation() {
global $product;
if ($product->product_type == "variable" && (is_product_category() || is_product_tag())) {
echo woocommerce_variable_add_to_cart();
}
}
Hi You can just paste this code in your theme functions.php
here is code
/**
* Replace add to cart button in the loop.
*/
function iconic_change_loop_add_to_cart() {
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
add_action( 'woocommerce_after_shop_loop_item', 'iconic_template_loop_add_to_cart', 10 );
}
add_action( 'init', 'iconic_change_loop_add_to_cart', 10 );
/**
* Use single add to cart button for variable products.
*/
function iconic_template_loop_add_to_cart() {
global $product;
if ( ! $product->is_type( 'variable' ) ) {
woocommerce_template_loop_add_to_cart();
return;
}
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
add_action( 'woocommerce_single_variation', 'iconic_loop_variation_add_to_cart_button', 20 );
woocommerce_template_single_add_to_cart();
}
/**
* Customise variable add to cart button for loop.
*
* Remove qty selector and simplify.
*/
function iconic_loop_variation_add_to_cart_button() {
global $product;
?>
<div class="woocommerce-variation-add-to-cart variations_button">
<button type="submit" class="single_add_to_cart_button button"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
<input type="hidden" name="add-to-cart" value="<?php echo absint( $product->get_id() ); ?>" />
<input type="hidden" name="product_id" value="<?php echo absint( $product->get_id() ); ?>" />
<input type="hidden" name="variation_id" class="variation_id" value="0" />
</div>
<?php
}
Even after so many years this one is not so simple for woocommerce.
The above examples shows the parent products with available variations below.
You maybe want to show the variations as simple products.
It's better to use a plugin for this. The Woocommerce single variations by weLaunch https://www.welaunch.io/en/product/woocommerce-single-variations/
it's the best i found so far. It gives you the opportunity to even exclude one variation from the category page (Most of the times, your products have 2 variations color/size. You simple want to show only the color variation).
If you want to go with custom code. You have to keep in mind, the images, pagination, filters, product links with variation parameters.
Woocommerce works with parent products on its core.

WooCommerce: How to display fields from the "Product Add-ons" extension?

I'm using the [Product Add-ons][1] extension for WooCommerce, which allows custom fields for products. This automatically displays on the single product template.
By some trial and error with the single product template, it appears to hook in somewhere in woocommerce_single_product_summary (single_meta?).
I need to get this same set of form fields to display on the archive-product template (the list of products). In my case, this is a field for a card request and one for delivery date. Both are needed before the product can be added to the cart from the product archive. I'm not sure if there is a function I can call for this, if it involves some more advanced coding.
Per Pelmered's answer, I was able to get the add-on fields to show up with adding this to functions.php:
add_action( 'woocommerce_after_shop_loop_item_title', array($GLOBALS['Product_Addon_Display'], 'display'), 10);
1ST ATTEMPT
Then, the problem was that the product archive was not creating a form element, only an anchor link for the add to cart button. So I've tried manually putting in a form. Code from content-product.php:
<?php do_action( 'woocommerce_before_shop_loop_item' ); ?>
<h2><?php the_title(); ?></h2>
<?php // MANUALLY PUT IN FORM, BECAUSE HOOKS ONLY PUT IN A BUTTON AND NO FORM. NEEDED FOR ADD-ON FIELDS ?>
<form class="cart" method="post" enctype='multipart/form-data'>
<?php
/**
* woocommerce_after_shop_loop_item_title hook
*
* #hooked woocommerce_template_loop_rating - 5
* #hooked woocommerce_template_loop_price - 10
*/
do_action( 'woocommerce_after_shop_loop_item_title' );
?>
<div itemprop="description">
<?php the_content(); ?>
</div>
<input type="hidden" name="add-to-cart" value="<?php echo esc_attr( $product->id ); ?>" />
<button type="submit" class="single_add_to_cart_button button alt"><?php echo $product->single_add_to_cart_text(); ?></button>
</form>
<?php //do_action( 'woocommerce_after_shop_loop_item' ); ?>
This worked, but kind of messes up the AJAX submission and flash messages. After clicking the add to cart button, the page appears to refresh, and then it looks like nothing happened. But when you go to another page, it displays the messages (and multiple can stack).
2ND ATTEMPT
So I saw that the original AJAX cart button (not within a form) was using a query string to send the product ID. So I am now attempting to tack on additional parameters by modifying the add to cart JS. This worked. What I did added as the accepted answer.
I've found a solution that works, using jQuery to add the form field values to the AJAX request. This requires overriding add-to-cart.js with your own version, so future updates to that file may need to be merged.
In functions.php
// display add-on fields in woocommerce_after_shop_loop_item_title
add_action( 'woocommerce_after_shop_loop_item_title', array($GLOBALS['Product_Addon_Display'], 'display'), 10);
// Our custom cart JS to allow for product add-on fields on product archive
add_action( 'wp_enqueue_scripts', 'load_woo_scripts', 9 );
function load_woo_scripts() {
wp_enqueue_script( 'wc-add-to-cart', get_template_directory_uri() . '/js/add-to-cart.js', array( 'jquery' ), WC_VERSION, true );
}
Duplicate /assets/add-to-cart.js from the woocommerce plugin folder, and add to the folder referenced in load_woo_scripts. Then add the following after the var date = { statement (line 21).
// =========================================================================
// ADD PRODUCT ADD-ON FIELDS TO SUBMISSION (to allow from product archive)
// Store name and value of fields in object.
var addonfields = {};
$(this).parent().find(".after-shop-loop-item-title :input").each(function() {
addonfields[this.name] = $(this).val();
});
// Merge new fields and existing data
data = $.extend(data, addonfields);
// Testing: final value of data
console.log( data );
// =========================================================================
This adds the names and values of all input fields within the .after-shop-loop-item-title div. I've added this div/class to my theme's woocommerce/content-product.php template:
<?php do_action( 'woocommerce_before_shop_loop_item' ); ?>
<h2><?php the_title(); ?></h2>
<div itemprop="description">
<?php the_content(); ?>
</div>
<div class="after-shop-loop-item-title">
<?php
/**
* woocommerce_after_shop_loop_item_title hook
*
* #hooked woocommerce_template_loop_rating - 5
* #hooked woocommerce_template_loop_price - 10
*/
do_action( 'woocommerce_after_shop_loop_item_title' );
?>
</div>
<?php do_action( 'woocommerce_after_shop_loop_item' ); ?>
Note that in my case, I am only using a textarea and a text input. Neither of which changes the price. More advanced usage of the extension may require more work.
I really hope that WooCommerce makes this easier in the future...
It's impossible to give you an exact copy-paste solution without access to the code, but it should be possible to attach the same function that is being hooked.
The hook that adds this to the single product page probably looks like this:
add_action( 'woocommerce_single_product_summary', array($this, 'woocommerce_product_add_ons_something'));
To attach this action to the achive template as well you should probably be able to do something like this:
add_action( 'woocommerce_after_shop_loop_item_title', array('WC_Product_Add_On', 'woocommerce_product_add_ons_something'));
WC_Product_Add_On is the class name of the plguin and needs to be changed to match the class that has the function/method in the action. Put this code in the functions.php file in your theme.
See if it works. If not, give me more information and I can expand my answer.
If anyone want to display woocommerce product addons fields everywhere, you can do this:
$custom_field = get_post_meta( $product_id, '_product_addons', false );
foreach( $custom_field as $field => $value) {
foreach( $value as $val => $v) {
echo $v["name"]; // or other field that you want!
}
}
Enjoy!

Resources