Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Woocommerce - Alternative for woocommerce_locate_template

I am developing a plugin based on woocommerce and as a part of the I had to override the default template file location of woocommerce. I mean I am looking to have a custom woocommerce template loaded from my plugin.

For doing this I read about woocommerce_locate_template in woocommerce based on this article, but I noticed that the same function has been deprecated as per this link. Now I am wondering what could be an alternative function for this.

My whole intention was to change the default woocommerce template loading location to my plugin folder. Any help in resolving this? Thanks in advance.

like image 591
krishna89 Avatar asked Sep 07 '15 22:09

krishna89


3 Answers

woocommerce_locate_template function is deprecated in favor of wc_locate_template: you can read the code here.

However, if you are looking for the filter, it's still woocommerce_locate_template and takes three arguments:

  1. $template that is the result of the wp core function locate_template
  2. $template_name that is only the filename
  3. $template_path that is the woocommerce path for templates

So you can check if the $template_name is what you want to intercept and change the path if true, like this

function intercept_wc_template($template, $template_name, $template_path) {
    if ($template_name == 'that_template.php') {
        $template = 'the/path/of/your/plugin/template.php';
    }
    return $template;
}

add_filter('woocommerce_locate_template', 'intercept_wc_template', 20, 3);

I've not tested it, so sorry for any possible syntax error :)

Hope it helps!

-- Update 1: I forgot a semicolon :P --
-- Update 2: I made a mistake! --

like image 150
Lorenzo Zottar Avatar answered Nov 20 '22 08:11

Lorenzo Zottar


I had to modify the above code in order to get it to correctly match the template file I needed, which in my case was "variable.php".

$template_name needs to be the full woocommerce root path, see below:

See the amended code below:

function intercept_wc_template($template, $template_name, $template_path) {
    if ($template_name == 'single-product/add-to-cart/variable.php') {
        $template = 'wp-content/themes/theme-name/woocommerce/single-product/add-to-cart/variable.php';
    }

    return $template;
}

add_filter('woocommerce_locate_template', 'intercept_wc_template', 20, 3);
like image 32
pixelkicks Avatar answered Nov 20 '22 08:11

pixelkicks


If someone struggle with this as of 2021, worth mention that the filter 'woocommerce_locate_template' does not filter all templates inside woocommerce folder. Instead, You need to filter 2 other functions:

add_filter('wc_get_template', 'entex_wc_get_template', 20, 5);
add_filter('wc_get_template_part', 'entex_wc_get_template_part', 20, 3);

For example, The root woocommerce template content-single-product.php must be filtered with wc_get_template_part.

This is working for our plugin:

function template_base(){
    return untrailingslashit(plugin_dir_path( __FILE__ )) .'/templates/';
}

function entex_wc_get_template($template, $template_name, $args, $template_path, $default_path){

    /* custom theme templates has priority */
    if(strpos($template, '/themes/') !== FALSE) return $template;

    static $cache = array();
    if(isset($cache[$template_name])) return $cache[$template_name];
    
    $plugin_template = wc_locate_template($template_name, WC()->template_path(), $this->template_base());
    if($plugin_template && file_exists($plugin_template)){
        $template = $plugin_template;
        $cache[$template_name] = $template;
    }
    return $template;
}

function entex_wc_get_template_part($template, $slug, $name){
    
    /* custom theme templates has priority */
    if(strpos($template, '/themes/') !== FALSE) return $template;
    
    $template_name = '';
    if($name){
        $template_name = "{$slug}-{$name}.php";
    } else if($slug){
        $template_name = "{$slug}.php";
    }
    if(!$template_name) return $template;
    
    static $cache = array();
    if(isset($cache[$template_name])) return $cache[$template_name];
    
    $plugin_template = template_base().$template_name;
    if($plugin_template && file_exists($plugin_template)){
        $template = $plugin_template;
        $cache[$template_name] = $template;
    }
    return $template;
} 

This is ripped out of the PHP class and pasted here so hopefully the code is not broken.

We recommend to register the templates for cleaner performance, if you only use a few, and add something like this early in the functions:

if(!in_array($template_name, array(
    'archive-product.php',
    'content-product.php',
    'content-product-cat.php',
    'content-single-product.php',
    'content-widget-product.php',
    'checkout/form-checkout.php',
    'checkout/thankyou.php',
    'loop/loop-start.php',
    'loop/loop-end.php'
))) return $template;
like image 41
Jonas Lundman Avatar answered Nov 20 '22 08:11

Jonas Lundman