Hi,
I want to override a woocommerce template in a plugin (I know how to do this in a theme but not a plugin), specifically single-product-reviews.php, this is located in themefolder/woocommerce/single-product-reviews.php
I have found this code:
function myplugin_plugin_path() {
// gets the absolute path to this plugin directory
return untrailingslashit( plugin_dir_path( __FILE__ ) );
}
add_filter( 'woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3 );
function myplugin_woocommerce_locate_template( $template, $template_name, $template_path ) {
global $woocommerce;
$_template = $template;
if ( ! $template_path ) $template_path = $woocommerce->template_url;
$plugin_path = myplugin_plugin_path() . '/woocommerce/';
// Look within passed path within the theme - this is priority
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
// Modification: Get the template from this plugin, if it exists
if ( ! $template && file_exists( $plugin_path . $template_name ) )
$template = $plugin_path . $template_name;
// Use default template
if ( ! $template )
$template = $_template;
// Return what we found
return $template;
}
which works perfectly for woocommerce template files that are one folder deep i.e /woocommerce/single-product but doesnt work in the parent directory i.e. /woocommerce
this is the hook, woocommerce_product_review_comment_form_args, I just don't know what I need to do?
Liam Bailey answers:
NEW SOLUTION AFTER CONVERSATION:
Ok,
I have found the problem. The single product reviews template isn't loaded like the others, see the comment_templates_loader function in woocommerce.php (around line 643 on mine). This is attached to the comments_template filter, so all we need to do is attach to the same filter on a later priority, and add our file like so:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path(__FILE__));
}
add_filter('comments_template','our_template',100,1);
function our_template($template) {
global $woocommerce;
if (get_post_type() == "product" && file_exists(myplugin_plugin_path() . "/woocommerce/single-product-reviews.php")) {
return myplugin_plugin_path() . "/woocommerce/single-product-reviews.php";
}
return $woocommerce->comments_template_loader($template);
}
ORIGINAL ANSWER:
The theme is the overriding template in the function you have above there. It is designed so you can override woocommerce templates in your plugin, but people can still override them in their themes. If you want to override a template that is in the theme, with one in your plugin then you have two choices: Either delete the file from the theme and use the function above as is OR Leave the template in your theme and remove this from your function
// Look within passed path within the theme - this is priority
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
Or make it check your plugin dir first before the theme, making your complete code:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path(__FILE__));
}
add_filter('woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3);
function myplugin_woocommerce_locate_template($template, $template_name, $template_path) {
global $woocommerce;
$_template = $template;
if (!$template_path)
$template_path = $woocommerce->template_url;
$plugin_path = myplugin_plugin_path() . '/woocommerce/';
//check for plugin override first:
if (!$template && file_exists($plugin_path . $template_name))
$template = $plugin_path . $template_name;
// THEN Look within the theme
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
// AND THEN Use default template
if (!$template)
return $template;
}
However, the best course of action for me when the client has already overridden the Woocommerce template in their theme is to simply make my changes to that template within their theme.
willcm comments:
Hi Liam,
Thanks for this, yes I thought the custom single-product-reviews.php template file I'd placed in the theme folder may have been blocking it so I deleted it from the theme folder and placed within the plugin file under plugin/woocommerce and it still doesn't work, which is strange as anything that is one folder deep does override the standard woocommerce templates?
I'd prefer it to be within the plugin so that in the future they dont have to manually drop single-product-reviews.php into the themefolder...
Thanks
Will
Liam Bailey comments:
Hi Willcim,
Have you checked to make sure your file is on the path being used in the function, as that function should override any Woocommerce template. Try putting your plugin first in the order it checks, making your code like so:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path(__FILE__));
}
add_filter('woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3);
function myplugin_woocommerce_locate_template($template, $template_name, $template_path) {
global $woocommerce;
$_template = $template;
if (!$template_path)
$template_path = $woocommerce->template_url;
$plugin_path = myplugin_plugin_path() . '/woocommerce/';
//check for plugin override first:
if (!$template && file_exists($plugin_path . $template_name))
$template = $plugin_path . $template_name;
// THEN Look within the theme
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
// AND THEN Use default template
if (!$template)
return $template;
}
And I know this will seem obvious, but make sure your file is being found on the path you are using in your plugin, I have lost count of the times I accidentally use underscores when the file I am overriding has hyphens etc.
willcm comments:
I get these errors with that code:
Warning: include() [function.include]: Filename cannot be empty in /home/willcm/public_html/pbs/wp-content/plugins/woocommerce/woocommerce-core-functions.php on line 633
Warning: include() [function.include]: Failed opening '' for inclusion (include_path='.:/usr/lib/php:/usr/local/lib/php') in /home/willcm/public_html/pbs/wp-content/plugins/woocommerce/woocommerce-core-functions.php on line 633
Thanks
Will
Liam Bailey comments:
There is an error in my code, but it has actuall helped us here. Note in my code after if (!$template) I have left out
$template = $_template;
The errors show that woocommerce has tried to include blank, meaning our filter returned nothing. It returned nothing because of what I left out, but this means it no file was found at your plugin locatuon or in the theme (because u deleted). You obvously have your path or filename wrong. For further proof of this add the file back into your theme and it will stop the errors. Please check your path/file and make my code as follows:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path(__FILE__));
}
add_filter('woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3);
function myplugin_woocommerce_locate_template($template, $template_name, $template_path) {
global $woocommerce;
$_template = $template;
if (!$template_path)
$template_path = $woocommerce->template_url;
$plugin_path = myplugin_plugin_path() . '/woocommerce/';
//check for plugin override first:
if (file_exists($plugin_path . $template_name))
return $plugin_path . $template_name;
// THEN Look within the theme
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
// AND THEN Use default template
if (!$template)
$template = $_template;
return $template;
}
willcm comments:
ok I've implemented the above code, the error have gone, but still not loading the custom template...
so I've deleted the custom single-product-reviews.php from /themefolder/woocommerce/single-product-reviews.php (where it was working)
and put this in pluginfolder/woocommerce/single-product-reviews.php
I've double/triple checked the filename and its single-product-reviews.php so no errors in terms of naming, but I'm clearly putting it in the wrong location because it's not loading, whereas (and I've tested this) if I put a file in pluginfolder/woocommerce/single-product/meta.php it works...
So where should I put files that are in the parent directory of woocommerce in my theme folder to get them to override??
Liam Bailey comments:
Ok, I am out, so I can't really answer definitiively, but try the following:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path(__FILE__));
}
add_filter('woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3);
function myplugin_woocommerce_locate_template($template, $template_name, $template_path) {
global $woocommerce;
$_template = $template;
if (!$template_path)
$template_path = $woocommerce->template_url;
$plugin_path = myplugin_plugin_path();
if (!strstr($plugin_path, 'woocommerce)) {
$plugin_path .= '/woocommerce/';
}
//check for plugin override first:
if (file_exists($plugin_path . $template_name))
return $plugin_path . $template_name;
// THEN Look within the theme
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
// AND THEN Use default template
if (!$template)
$template = $_template;
return $template;
}
willcm comments:
still exactly the same, it's bizarre because it override in the theme directory but not the plugin directory if in the parent woocommerce template directory I just don't get it!
is there a way to do it like this?
[[LINK href="https://github.com/woothemes/woocommerce/issues/1646"]][[/LINK]]
willcm comments:
https://github.com/woothemes/woocommerce/issues/1646
willcm comments:
so...
woocommerce_get_template( 'cool-template.php', FALSE, FALSE, untrailingslashit( plugin_dir_path( __FILE__ ) ) . '/templates/');
how would I code that to modify single-product-reviews.php
Liam Bailey comments:
Hang on a minute... What location is the file you are running the code we have been working on in?
If it is not in the same directory as the woocommerce directory you are storing your templates in then this is the problem. The code which sets the path to look in for templates is:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path(__FILE__));
}
This sets a path to the folder of the file it is run in, so if you are in /my-plugin/php or my-plugin/lib and the woocommerce folder for your overriding templates is directly off the base my-plugin directory then you are looking in the wrong place, i.e. my-plugin/lib/woocommerce is where you are looking.
There are two ways around this: run the code from the right place, or set the path like this:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path("/my-plugin/plugin_file.php"));
}
Where plugin_file.php is any php file in the base directory of the plugin. But in your case the best way would be to set the path off of the template file you are trying to override. I.e.
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path("/my-plugin/woocommerce/single-reviews-template.php));
}
This will give you a path right to the woocommerce folder, I have put the full code using this new method below - change my-plugin to whatever the directory is for your plugin. Now this should work, I have gone through all the woocommerce code and there is nothing to stop this from working. If it doesn't perhaps I can give you my email and take a look via ftp.
function myplugin_plugin_path() {
//change my-plugin below
return plugin_dir_path("/my-plugin/woocommerce/single-reviews-template.php);
}
add_filter('woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 30, 3);
function myplugin_woocommerce_locate_template($template, $template_name, $template_path) {
global $woocommerce;
$_template = $template;
if (!$template_path)
$template_path = $woocommerce->template_url;
$plugin_path = myplugin_plugin_path();
//check for plugin override first:
if (file_exists($plugin_path . $template_name))
return $plugin_path . $template_name;
// THEN Look within the theme
$template = locate_template(
array(
$template_path . $template_name,
$template_name
)
);
// AND THEN Use default template
if (!$template)
$template = $_template;
return $template;
}
willcm comments:
Still doesnt work :-/
My plugin looks like this:
wp-content/plugins/myplugin
- woocommerce <-folder which contains one file -> single-product-reviews.php (template I want to override)
- pluginfunctions.php
I guess the point is that the override is working with the original code, so we know that the code is working, but only when it's one folder deep i.e. wp-content/plugins/myplugin/woocommerce/single-product/meta.php is there a different function that overrides the templates in the root of the woocommerce templates i.e. wp-content/plugins/myplugin/woocommerce. This isn't just a problem I'm having if you look here where I got my original code http://www.skyverge.com/blog/override-woocommerce-template-file-within-a-plugin/ the comments at the bottom also suggest people are having problems overriding the templates in the root of the woocommerce templates?
SOOOOOOOOOO FRUSTRATING!
Liam Bailey comments:
Ok,
I have found the problem. The single product reviews template isn't loaded like the others, see the comment_templates_loader function in woocommerce.php (around line 643 on mine). This is attached to the comments_template filter, so all we need to do is attach to the same filter on a later priority, and add our file like so:
function myplugin_plugin_path() {
return untrailingslashit(plugin_dir_path(__FILE__));
}
add_filter('comments_template','our_template',100,1);
function our_template($template) {
global $woocommerce;
if (get_post_type() == "product" && file_exists(myplugin_plugin_path() . "/woocommerce/single-product-reviews.php")) {
return myplugin_plugin_path() . "/woocommerce/single-product-reviews.php"
}
return $woocommerce->comments_template_loader($template);
}
Liam Bailey comments:
Note the missing semi-colon after: return myplugin_plugin_path() . "/woocommerce/single-product-reviews.php"
in my final answer.
I have posted the correct version of the code atop my original answer anyway.
zebra webdesigns answers:
Hello Willcm
are you developing your own plugin or customizing existing one.
If so specify the functionality or the plugin name.
willcm comments:
Developing a new plugin to override and edit woocommerce reviews, no name yet...
Arnav Joy answers:
have you check this tutorial?
http://www.skyverge.com/blog/override-woocommerce-template-file-within-a-plugin/
willcm comments:
yes that's where I got the above code from, if you look at the comments section at the bottom other people seem to be having issues with templates in the parent directory of the template folder also...
willcm comments:
Is there a way I can override just the single-product-reviews.php using the hook woocommerce_product_review_comment_form_args ?