How to override the category template on the /shop/ page when showing filtered products? - woocommerce

I already created a function that will filter products using URL parameters and display them on the /shop/ page. That works fine.
But, that only works if the products template is set on the WooCommerce /shop/ page.
In my case the requirement is to have the category list set as default template on the /shop/ page. That means I need to override that template and show the filtered product list, when I run a product query with URL parameters.
(eg. example.com/shop/?param1=foo&param2=bar)
I tried following code (and some iterations), but I'm stuck and have no clue how to override the default template when a product filter is applied:
add_filter( 'woocommerce_locate_template', [$this, 'my_include_template_function'], 10, 3 );
public function my_change_template_function($template, $template_name, $template_path)
{
if (!empty($_GET['param1']) && is_shop() && $template_name == 'content-product_cat.php') {
return wc_get_template_part('content', 'product');
} else {
return $template;
}
}

So the source of the categories loop is added in to the loop start [via a filter][1]
add_filter( 'woocommerce_product_loop_start', 'woocommerce_maybe_show_product_subcategories' );
and the woocommerce_maybe_short_product_subcategories() function changes the output based on the:
$display_type = woocommerce_get_loop_display_mode();
However, the woocommerce_get_loop_display_mode() result isn't filterable directly.
But it relies on some values from get_option() (since the setting is in the customizer) and get_option() is filterable via option_$option
So a potential way to tell WooCommerce not to display the categories when you have a particular $_GET parameter, you could filter the shop display mode option to be products when that parameter is detected in the URL. Like this:
/**
* Filter shop display type.
*
* #param string $value - 'products' | 'subcategories' | 'both'
* #return string
*/
function kia_woocommerce_shop_page_display( $value ) {
if ( ! empty( $_GET['param1'] ) {
$value = 'products';
}
return $value;
}
add_filter( 'option_woocommerce_shop_page_display', 'kia_woocommerce_shop_page_display' );

Related

Getting product stock quantity isn't working

On single product page I'm trying to get stock quantity or atleast stock status from woocommerce product but it seems not working properly, even if it's simple product (manage stock status is checked) or variable product the button is not showing. And strange thing happens - I've got Yith Product Bundle plugin and even if every item is in stock it shows that button but whatever, that's not main problem.
So here is code I'm using
add_action('woocommerce_before_add_to_cart_button', 'show_wishlist');
function show_wishlist() {
global $product;
$stockQ=$product->get_stock_quantity();
if ( $stockQ < 1 ) {
echo "<button>Hello</button>";
}
}
I've also tried but completely nothing happens.
add_action('woocommerce_before_add_to_cart_button', 'show_wishlist');
function show_wishlist() {
global $product;
if ( ! $product->is_in_stock() ) {
echo "<button>Hello</button>";
}
}
First check if the hook is firing properly.
add_action( 'woocommerce_before_add_to_cart_button', 'show_wishlist' );
function show_wishlist(){
echo '<p>Some custom text before</p>';
}
If you are able to confirm that the hook is working then use the below code.
function show_wishlist() {
global $product;
// Change In Stock Text
if ( $product->managing_stock() && $product->is_in_stock() ) {
//add your code here for Products in Stock
}
else{
//add your code here for Products out of Stock
}
}

Override wordpress routing / url rewriting?

I would like to serve different content based on the URL.
I started with a custom page setup via a custom template but I am open to something else.
The main goal is to have one PHP page that can serve different contents programmatically based on the URL.
For example:
https://some-url.com/my-plugin/ -> run my page
https://some-url.com/my-plugin/foo/ -> run my page
https://some-url.com/my-plugin/foo2/abc/ -> run my page
etc...
I have been looking at add_rewrite_rule, add_rewrite_tag, flush_rewrite_rules and WP_Rewrite API but I am getting confused about which one I should use?
I found an example here but I could not make it work, I get 404s, any idea why?:
/*
Plugin Name: Products Plugin
Plugin URI: http://clivern.com/
Description: Register URL rules for our products
Version: 1.0
Author: Clivern
Author URI: http://clivern.com
License: MIT
*/
function products_plugin_activate() {
products_plugin_rules();
flush_rewrite_rules();
}
function products_plugin_deactivate() {
flush_rewrite_rules();
}
function products_plugin_rules() {
add_rewrite_rule('products/?([^/]*)', 'index.php?pagename=products&product_id=$matches[1]', 'top');
}
function products_plugin_query_vars($vars) {
$vars[] = 'product_id';
return $vars;
}
function products_plugin_display() {
$products_page = get_query_var('pagename');
$product_id = get_query_var('product_id');
if ('products' == $products_page && '' == $product_id):
//show all products
exit;
elseif ('products' == $products_page && '' != $product_id):
//show product page
exit;
endif;
}
//register activation function
register_activation_hook(__FILE__, 'products_plugin_activate');
//register deactivation function
register_deactivation_hook(__FILE__, 'products_plugin_deactivate');
//add rewrite rules in case another plugin flushes rules
add_action('init', 'products_plugin_rules');
//add plugin query vars (product_id) to wordpress
add_filter('query_vars', 'products_plugin_query_vars');
//register plugin custom pages display
add_filter('template_redirect', 'products_plugin_display');
First of all, make sure your pretty permalinks are enabled, in this case the option "Plain" in Settings - Permalinks should be unselected:
Select one of these options to enable pretty permalinks
You can check whether pretty permalinks are enabled in the code like so:
function is_enabled_pretty_permalinks() {
return !empty( get_option( 'permalink_structure' ) );
}
if ( is_enabled_pretty_permalinks() ) {
echo 'Pretty permalinks enabled';
}
Next add a new rewrite rule:
function add_my_rewrite_rule() {
$page_slug = 'products'; // slug of the page you want to be shown to
$param = 'do'; // param name you want to handle on the page
add_rewrite_rule('my-plugin/?([^/]*)', 'index.php?pagename=' . $page_slug . '&' . $param . '=$matches[1]', 'top');
}
add_action('init', 'add_my_rewrite_rule');
Add your parameter to query vars so you will be able to handle it on the page:
function add_my_query_vars($vars) {
$vars[] = 'do'; // param name you want to handle on the page
return $vars;
}
add_filter('query_vars', 'add_my_query_vars');
Then you can access your query var do in the page template or in a shortcode, for example:
function my_plugin_shortcode_handler( $atts ){
$do = get_query_var( 'do' );
if ( $do === 'this' ) {
return 'do this';
} else {
return 'do that';
}
}
add_shortcode( 'myshortcode', 'my_plugin_shortcode_handler' );
Then place the shortcode to the content via Gutenberg.
Check out the links:
https://some-url.com/my-plugin/this/ - outputs "do this"
https://some-url.com/my-plugin/that/ - outputs "do that".
This can be solved by using query params. Like you mentioned you have set up custom page via a custom template. You can read the URL and check for the parameters and based on that you can send data from the PHP template page.
e.g,
function cleanTheInput($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
$data = htmlentities($data);
return $data;
}
if (isset($_GET['page_url'])) {
$theUrl = cleanTheInput($_GET['page_url']);
}
if($theUrl == 266)){
// data for https://some-url.com/?page_url=266
}
if($theUrl == 366)){
// data for https://some-url.com/?page_url=366
}

Show Advanced custom field in wpallexport

I wanted to export a Advanced custom field and therefore I used the Function Editor in wpallexport, but nothing is showing up.
I created a ACF field for the product in woocommerce (wirtschaftlicher_eigentumer), I tried to get it over the product_id but nothing appears.
function wirtschaftlicher_eigen ($product_id) {
if ( ! empty($product_id) ) {
return get_field('wirtschaftlicher_eigentumer', 'product_' . $product_id);
}
}
Want to get the field but instead it's empty.
You need to change
return get_field('wirtschaftlicher_eigentumer', 'product_' . $product_id);
To
return get_field('wirtschaftlicher_eigentumer', $product_id);
The $product_id will return the current post id.

How to disable Yoast SEO adding article:author meta tags to pages

The excellent Yoast SEO plugin is adding some unwanted meta tags.
For example, I would like article:author to appear on posts, but not on pages or other content types.
Is there a way to adjust this globally?
I'm happy to edit functions.php, but I'm just unsure what I should be hooking in to.
I would be grateful for any pointers from those more familiar with the plugin.
I tried this:
function wpseo_show_article_author_only_on_posts() {
if ( !is_single() ) {
return false;
}
}
add_filter( 'xxxxxx', 'wpseo_show_article_author_only_on_posts' );
I need to know what hook should replace xxxxxx.
You're looking for the wpseo_opengraph_author_facebook filter, which ties into the article_author_facebook() method in frontend/class-opengraph.php of the plugin.
function wpseo_show_article_author_only_on_posts( $facebook ) {
if ( ! is_single() ) {
return false;
}
return $facebook;
}
add_filter( 'wpseo_opengraph_author_facebook', 'wpseo_show_article_author_only_on_posts', 10, 1 );
The article_author_facebook() method does a check for is_singular(), which checks that we're viewing single page, post or attachment:
This conditional tag checks if a singular post is being displayed, which is the case when one of the following returns true: is_single(), is_page() or is_attachment(). If the $post_types parameter is specified, the function will additionally check if the query is for one of the post types specified.
The additional filter for ( ! is_single() ) ensures that article:author is only added to posts.
If people are looking for a way to remove more yoast SEO tags, just lookup the file wordpress-seo/frontend/class-opengraph.php, and you can see which filters you can hook into to remove certain tags.
This is the code I use to remove these tags from pages: url, image, title, description and type:
function remove_yoast_og_tags( $ogTag ){
// Do a check of which type of post you want to remove the tags from
if ( is_page() ) {
return false;
}
return $ogTag;
}
$yoastTags = array(
"url",
"image",
"title",
"desc",
"type"
);
foreach ($yoastTags as $tag) {
add_filter( 'wpseo_opengraph_'.$tag, 'remove_yoast_og_tags');
}

Woocommerce choose grid or list view for each category

I want the possibility to choose between grid and list view for each Woocommerce category. I have found this plugin: https://nl.wordpress.org/plugins/woocommerce-grid-list-toggle/
However, the plugin is meant for the shopper to choose whether to display items in grid view or list view. What I truly want is the ability to assign a view for each category in the back-end.
Example:
Category A is displayed as grid
Category B is displayed as list
Breaking my head over this.
Similar to this question you need to filter template_include. You need to call your custom archive template archive-list-view.php and save it in your theme's woocommerce folder. Obviously, you can name it anything you like, you will just have to adjust the code below to match.
Folder structure:
/theme-folder/functions.php
/theme-folder/woocommerce/archive-list-view.php
On the template_include filter we will check if we are on the term archive for the nussmylch product category. If so, we'll look for and supply the new template. Otherwise, the standard template is used.
EDIT: incorrect WooCommerce function is_product_taxonomy() was used. is_product_category() is needed to check for a specific category.
add_filter( 'template_include', 'so_33615903_custom_category_template', 20 );
function so_33615903_custom_category_template( $template ) {
// check you are on the taxonomy archive for specific category
if ( is_product_category( 'nussmylch' ) ) {
$new_template = locate_template( array( 'woocommerce/archive-list-view.php' ) );
if ( '' != $new_template ) {
$template = $new_template ;
}
}
return $template;
}
Working Example

Resources