To begin with, my problem:
I have a WooCommerce error on the W3C Validator platform.
I overwrite the file by redirecting the template path of WooCommerce for that specific file.
Problem:
The Wordpress Theme that I am currently using is also overwritting the same file as my Custom plugin, as a result the Theme's overwriting cancels out my plugin's overwritting functionality.
CODE:
Here's some of my code:
This is the function I add using the built in wordpress function add_filter() with high priority value of "1" plus the path of the file I am overwritting is... woocommerce/templates/single-product/add-to-cart/variable.php
function wc_locate_template( $template, $template_name, $template_path ) {
// Check if WooCommerce is present on the website
if ( empty( $template ) || ! is_callable( 'WC' ) || ( defined( 'WC_TEMPLATE_DEBUG_MODE' ) && WC_TEMPLATE_DEBUG_MODE ) ) {
return $template;
}
// Variables
$default_path = WC()->plugin_path() . '/templates/';
$plugin_path = untrailingslashit( plugin_dir_path( __FILE__ ) ) . '/templates/';
$template_new = str_replace( $default_path, $plugin_path, $template );
// Processing
if (
false !== strpos( $template, $default_path )
&& file_exists( $template_new )
) {
$template = $template_new;
}
// Output
return $template;
}
add_filter( 'woocommerce_locate_template', 'wc_locate_template', 1, 3 );
Questions:
How can I make sure that my plugin will overwrite the file of in such way or prority so that the theme's overwritting won't overlap it?
Useful links:
Woocommerce Link
W3C Validator Link
Wordpress Link
Thank you in advance for your time.
priority 1 means your function will be applied first, so any other function attached to the filter with a number higher than 1 will simply overwrite your function.
You need to put highest possible number to make sure your function will be the last one applied.
use PHP_INT_MAX to make your function the last one applied.
add_filter( 'woocommerce_locate_template', 'wc_locate_template', PHP_INT_MAX, 3 );
That's an example on how to override a woocommerce template with a plugin:
add_filter( 'woocommerce_locate_template', 'woo_custom_template', 1, 3 );
function woo_custom_template( $template, $template_name, $template_path ) {
global $woocommerce;
$_template = $template;
if ( ! $template_path )
$template_path = $woocommerce->template_url;
$plugin_path = untrailingslashit( plugin_dir_path( __FILE__ ) ) . '/templates/';
// Within passed path within the theme - this is priority
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
// Processing
if( ! $template && file_exists( $plugin_path . $template_name ) )
$template = $plugin_path . $template_name;
if ( ! $template )
$template = $_template;
//Output
return $template;
}
Then you should be able to reach your goal by copying the template you want to override in your plugin folder.
Example:
your_plugin/template/WooCommerce/single-product/add-to-cart/variable.php
Hooks and filter are modification which runs based on priority,
the highest the priority before its being called will be the its final output
Here's an example
Assuming I have this function
function youFree() {
$imFree = apply_filters('free_filter', 'I am free' );
return $imFree;
}
then I have all these filters with different priorities
add_filter('free_filter', function() {
return 'You are not 1';
}, 1);
add_filter('free_filter', function() {
return 'You are not 10';
}, 10);
add_filter('free_filter', function() {
return 'You are not 999';
}, 999);
add_action('init', function() {
add_filter('free_filter', function() {
return 'You are not init 999';
}, 999);
});
add_action('wp_footer', function() {
add_filter('free_filter', function() {
return 'You are not wp_footer';
}, 999);
});
Here is the output
if you call youFree() on wp_head
add_action('wp_head', function() {
echo '<pre>', print_r(youFree(), 1), '</pre>';
});
//the output is "You are not init 999"
//because the add_filter that runs on wp_footer did not take effect
//as the function is already called way higher specifically in wp_head
//and the final value is last filter being called thats added on init hook with 999 priority
but if you call that youFree() function on wp_footer
add_action('wp_footer', function() {
echo '<pre>', print_r(youFree(), 1), '</pre>';
}, 20);
//the output is "You are not wp_footer"
//as this was the very last filter before that function is called on wp_footer
So in your situation,
You have to determine at which point the theme do the modification and at which point the value is being called.
Then you need to inject your filter after your theme modifies it and before it was called by woocommerce. Usually, this is as easy as looking at where the theme calls the filter and adding a priority on your filter which is higher than whats on the theme filter.
but if your having a hard at where to inject it your best option is to find it using query monitor
First of all, I'm not a developer. I've managed to insert some functions for my WooCommerce webshop by inserting code snippets into the functions.php file of my parent theme. I've made a child theme in case I have to update the theme. I'm afraid these functions get lost otherwise.
I've used the Child Theme Configurator plugin to create the child theme. Now I'm trying to insert the same code snippets into the functions.php file of the child theme. I however, break my site every time. Before adding the code I've removed the functions from the parent theme, otherwise an overlap might excist.
I think I'm adding these code snippets at the wrong location within the file. Below you see the code from the child theme:
<?php
// Exit if accessed directly
if ( !defined( 'ABSPATH' ) ) exit;
// BEGIN ENQUEUE PARENT ACTION
// AUTO GENERATED - Do not modify or remove comment markers above or below:
if ( !function_exists( 'chld_thm_cfg_locale_css' ) ):
function chld_thm_cfg_locale_css( $uri ){
if ( empty( $uri ) && is_rtl() && file_exists( get_template_directory() . '/rtl.css' ) )
$uri = get_template_directory_uri() . '/rtl.css';
return $uri;
}
endif;
add_filter( 'locale_stylesheet_uri', 'chld_thm_cfg_locale_css' );
if ( !function_exists( 'child_theme_configurator_css' ) ):
function child_theme_configurator_css() {
wp_enqueue_style( 'chld_thm_cfg_child', trailingslashit( get_stylesheet_directory_uri() ) . 'style.css', array( 'hello-elementor','hello-elementor','hello-elementor-theme-style' ) );
}
endif;
add_action( 'wp_enqueue_scripts', 'child_theme_configurator_css', 10 );
// END ENQUEUE PARENT ACTION
This is the code I've successfully added to the parent theme. Now I want to add it to the child theme:
add_filter( 'woocommerce_product_tabs', 'woo_remove_product_tabs', 98 );
function woo_remove_product_tabs( $tabs ) {
unset( $tabs['description'] ); // Remove the description tab
unset( $tabs['additional_information'] ); // Remove the additional information tab
return $tabs;
}
/* melding uitschakelen: toegevoegd aan winkelwagen */
add_filter( 'wc_add_to_cart_message_html', 'ql_remove_add_to_cart_message' );
function ql_remove_add_to_cart_message( $message ){
return '';
}
Where and how do I add it?
Thanks for the help in advance! :)
In my plug-in i'm trying to override part of the theme's template with a template of my own but I'm struggling to get it to work.
add_filter( 'template_include', 'demo_page_template');
function demo_page_template($template) {
if ( is_product() ) {
$template = untrailingslashit( plugin_dir_path( __FILE__ ) ) . 'templates/woocommerce/single-product.php';
}
return $template;
}
I have added the appropriate files and folders but I'm not getting any reaction.
thanks for reading, appreciate any help I can get.
How am I supposed to call a secondary PHP file? Here is my code.
add_filter( 'woocommerce_product_tabs', 'woo_simfree_product_tab' );
function woo_simfree_product_tab( $tabs ) {
global $post;
if( function_exists('get_product') ){
$product = get_product( $post->ID );
if( $product->is_type( 'grouped' ) ){
$tabs['simfree-plans'] = array( 'title' => __( 'SIM Free', 'woocommerce' ), 'priority' => 20, 'callback' => 'woo_simfree_product_tab_content' );
return $tabs;
} else {
return $tabs;
}
}
}
function woo_simfree_product_tab_content() {
require get_template_directory() . "/custom-groups/grouped-simfree.php";
}
The problem is fetching the file right here... (3rd line from the bottom)
require get_template_directory() . "/custom-groups/grouped-simfree.php";
This does not work and causes strange behaviour. I have a custom PHP file I want to load in this tab I have created (grouped-simfree.php) but I don't know how to make it run.
What is the correct way to load a custom PHP file in wordpress from a function on a hook?
EDIT: (What's wrong with this picture?) I actually solved this problem years ago but now I've come back to the same problem but the same solution is not working for some reason. source (my question from 2014): https://stackoverflow.com/questions/30233440/woocommerce-woocommerce-grouped-add-to-cart-function
function woocommerce_grouped_add_to_cart2() {
global $product;
wc_get_template( get_template_directory() . '/custom-groups/grouped-simfree.php', array(
'grouped_product' => $product,
'grouped_products' => $product->get_children(),
'quantites_required' => false
) );
}
function woo_simfree_product_tab_content() {
woocommerce_grouped_add_to_cart2();
}
EDIT 2
If I move the custom template into the woocommerce plugin templates folder.
#Reigel this works but now im gonna lose the template when ever I update woocommerce I just realised this is what I did a couple years ago and now I realise why my site crashed because the templates were overwritten during a woocommerce update
function woocommerce_grouped_add_to_cart2() {
global $product;
wc_get_template( 'single-product/add-to-cart/grouped-simfree.php', array(
'grouped_product' => $product,
'grouped_products' => $product->get_children(),
'quantites_required' => false
) );
}
function woo_simfree_product_tab_content() {
woocommerce_grouped_add_to_cart2();
}
You'll need to use get_stylesheet_directory() to include your file, if it's a child theme do something like this:
require get_stylesheet_directory() . "/custom-groups/grouped-simfree.php";
The file should be at wp-content/themes/your-child-theme/custom-groups/grouped-simfree.php
I have plugin that create new post type. Also plugin set single template for it's single page.
add_filter( 'single_template', array( &$this, 'register_ipa_product_post_type_single_template' ) );
function register_ipa_product_post_type_single_template( $single_template ) {
global $post;
if ( $post->post_type == 'product' ) {
$single_template = IPA_PRODUCT_POST_TYPE_TEMPLATE_FOLDER . 'single-product.php';
}
return $single_template;
}
How i can override single-product.php in my theme.
I don't found any solutions for my question at this site.
just filter it a little later than the current function (ps if doing this within a class you need to reference it using array(&$this, 'function'). I left it out as i assume you are using the functions.php or function override....etc
add_filter( 'single_template', 'register_ipa_product_post_type_single_template', 100 );
function change_temp( $single_template ) {
global $post;
if ( $post->post_type == 'product' ) {
$single_template = 'path to your template file';
}
return $single_template;
};