Activate Woocommerce image gallery features on shop archive page - wordpress

I'm trying to build a Woocommerce shop with all products listed with full product information (excerpts, pictures, title, price, etc.) on the shop archive page. No product detail pages.
I have loaded the simple-page content instead of page-content in the loop of my custom archive-product.php in my theme/woocommerce folder.
My problem is, that the product image gallery features (zoom, lightbox, slider) don't work on the archive page, only on single-product-page.
How can I unlock the gallery features for the shop and category archive pages?
I think, that wordpress or woocommerce somehow deactivated certain javascript or php functions for the gallery features on this page. But I couldn't figure out where to make changes in order to bring them back in.
Here is the code I use for the loop in my moded archive-product.php. I simply changed 'product' to 'single-product' in order to load the full product content:
<?php while ( have_posts() ) : the_post(); ?>
<?php
/**
* woocommerce_shop_loop hook.
*
* #hooked WC_Structured_Data::generate_product_data() - 10
*/
do_action( 'woocommerce_shop_loop' );
?>
<!-- This part of the template has been moded for the product archive page to show the complete content of the single product page -->
<?php wc_get_template_part( 'content', 'single-product' ); ?>
<?php endwhile; // end of the loop. ?>

In case anyone ever has the same problem as me and wants to activate the woocommerce image gallery features on the archive page same as on the product page, add this code to the functions.php in your theme folder:
add_action( 'wp_enqueue_scripts', 'gallery_scripts', 20 );
function gallery_scripts() {
if ( is_archive()) {
if ( current_theme_supports( 'wc-product-gallery-zoom' ) ) {
wp_enqueue_script( 'zoom' );
}
if ( current_theme_supports( 'wc-product-gallery-slider' ) ) {
wp_enqueue_script( 'flexslider' );
}
if ( current_theme_supports( 'wc-product-gallery-lightbox' ) ) {
wp_enqueue_script( 'photoswipe-ui-default' );
wp_enqueue_style( 'photoswipe-default-skin' );
add_action( 'wp_footer', 'woocommerce_photoswipe' );
}
wp_enqueue_script( 'wc-single-product' );
}
}

Related

Custom Theme Single Product Page Wordpress/Woocommerce

I am building my custom theme and my single.php displays woocommerce single product page with
if ( have_posts() ) {
while( have_posts() ) {
the_post();
the_content();
}
}
Why is the page missing - title, reviews & breadcrumbs?
Woocommerce has its own templates for their pages. A single product should be showing on single-product.php. You would create a woocommerce folder inside your custom theme and copy the directories and files you want to edit over to your theme.
How to override single-product.php
If you want to custimize the single-product.php, you would create a woocommerce folder in your theme and copy the single-product.php over into it. So the directory would be yourtheme/woocommerce/templates/single-product.php. This way you have all the actions hooking in the functionality you are missing.
Here are the docs:
https://woocommerce.com/document/template-structure/
function mytheme_add_woocommerce_support() {
add_theme_support( 'woocommerce' );
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
}
add_action( 'after_setup_theme', 'mytheme_add_woocommerce_support' );
Please add this one in the functions.php file
I was missing
add_theme_support('woocommerce');
in my functions.php file

How to get product data in header.php file wordpress woocommerce

I want to show something of product like: name, price, sku in the header.php file.
Below is my code to get product in header.php
global $product;
var_dump($product);
But var_dump just show me the product name like string(6) "hoodie", not array of product.
So, how can I get the product data in header.php file.
Thank you.
Use the Wordpress get_the_ID() function.
Wordpress - get_the_ID()
Obviously this will only work if you are on the product page, so you can add an extra control with WooCommerce's is_product() function.
WooCommerce - is_product()
Finally, to add custom code in the header you can use the wp_head hook.
Wordpress - wp_head
So the function will look like:
// gets the product data in the header
add_action( 'wp_head', 'get_product_data' );
function get_product_data() {
// only on the product page
if ( ! is_product() ) {
return;
}
// gets the product object
$product = wc_get_product( get_the_ID() );
?>
HTML CODE HERE
<?php
}
Tested and it works. The code goes into your active theme's functions.php file.

Hide add to cart button in WooCommerce but show stock status

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 );

Customize the search results page in a Wordpress Genesis child theme

I am using Wordpress and the Genesis framework for a site. I'm using a child theme (Ayoshop - not that it matters much) for the theme. I would like to customize the search results page by removing the 'post info' area where it shows the date, author, and 'leave a comment' link, and instead show the featured image for that post. The theme is using the search.php page from the Genesis theme, so I'm not really sure how to proceed in how to customize it.
Here is the code from the Genesis theme search.php:
add_action( 'genesis_before_loop', 'genesis_do_search_title' );
/**
* Echo the title with the search term.
*
* #since 1.9.0
*/
function genesis_do_search_title() {
$title = sprintf( '<div class="archive-description"><h1 class="archive-title">%s %s</h1></div>', apply_filters( 'genesis_search_title_text', __( 'Search Results for:', 'genesis' ) ), get_search_query() );
echo apply_filters( 'genesis_search_title_output', $title ) . "\n";
}
genesis();
It actually did matter that it was the Ayoshop theme, there was a custom filter that was added in a file called theme-tweaks.php that removed the original post info and added a custom post info, so I needed to remove that custom action.
All of the changes were done in the functions.php file.
I made sure to remove the genesis_post_info, and then removed the custom action that Ayoshop added.
remove_action( 'genesis_before_post_content', 'genesis_post_info' );
remove_action( 'genesis_before_post_content', 'ayo_post_info' );
I then added an action to add the image to the post.
add_action ( 'genesis_before_post_content', 'jl_post_info' );
function jl_post_info()
if ( has_post_thumbnail() ) {
printf( '<div class="post-info">' . get_the_post_thumbnail() . '</div>');
}
}

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