WooCommerce plugin template overriding - wordpress

I am developing a WooCommerce plugin (actually usual WP plugin, but works only when WooCommerce enabled), which should to change standard WooCommerce output logic. In particular I need to override standard archive-product.php template by my own.
I have found there is no problem to change template in theme, but can not how to do it in the plugin. How I can do it without any changes in WP & WooCommerce cores?

I think you need to do it via hooks (filters & actions) available for WooCommerce.
Here is a list:
http://docs.woothemes.com/document/hooks/#templatehooks
Here is where to get started on hooks:
http://wp.tutsplus.com/tutorials/the-beginners-guide-to-wordpress-actions-and-filters/

Here is I try something like this. Hope it will help.
Add this filter into your plugin:
add_filter( 'template_include', 'my_include_template_function' );
And then the callback function will be
function my_include_template_function( $template_path ) {
if ( is_single() && get_post_type() == 'product' ) {
// checks if the file exists in the theme first,
// otherwise serve the file from the plugin
if ( $theme_file = locate_template( array ( 'single-product.php' ) ) ) {
$template_path = $theme_file;
} else {
$template_path = PLUGIN_TEMPLATE_PATH . 'single-product.php';
}
} elseif ( is_product_taxonomy() ) {
if ( is_tax( 'product_cat' ) ) {
// checks if the file exists in the theme first,
// otherwise serve the file from the plugin
if ( $theme_file = locate_template( array ( 'taxonomy-product_cat.php' ) ) ) {
$template_path = $theme_file;
} else {
$template_path = PLUGIN_TEMPLATE_PATH . 'taxonomy-product_cat.php';
}
} else {
// checks if the file exists in the theme first,
// otherwise serve the file from the plugin
if ( $theme_file = locate_template( array ( 'archive-product.php' ) ) ) {
$template_path = $theme_file;
} else {
$template_path = PLUGIN_TEMPLATE_PATH . 'archive-product.php';
}
}
} elseif ( is_archive() && get_post_type() == 'product' ) {
// checks if the file exists in the theme first,
// otherwise serve the file from the plugin
if ( $theme_file = locate_template( array ( 'archive-product.php' ) ) ) {
$template_path = $theme_file;
} else {
$template_path = PLUGIN_TEMPLATE_PATH . 'archive-product.php';
}
}
return $template_path;
}
I check this for theme first loading. If the file is not found in theme then it will load from the plugin.
You can change the logic here.
Hope it will do your work.
Thanks

Related

Woocommerce order_review custom template on cart items update

I have develop a custom template for woocommerce checkout page and added all templates that I need to change specifically order_review.php in plugin/woocommerce/checkout/order_review.php and on order page it works perfect.
From Order page I can remove some products or add products through ajax and here is my ajax code.
ob_start();
woocommerce_order_review();
$woocommerce_order_review = ob_get_clean();
$response = array(
'cart_total' => WC()->cart->total,
'cart_item_key' => $new_key,
'fragments' => apply_filters(
'woocommerce_update_order_review_fragments',
array(
'.woocommerce-checkout-review-order-table' => $woocommerce_order_review,
)
),
);
if ( ! empty( $data ) ) {
$response['cartflows_data'] = $data;
}
return $response;
And the woocommerce_order_review(); loads woocommerce default template instead of template from my plugin.
WooCommerce does not look in plugin folders for templates by default. You need to use the filter woocommerce_locate_template in your plugin to tell WooCommerce to look in your plugin folder for templates. The solution is outlined by SkyVerge in this blog post: https://www.skyverge.com/blog/override-woocommerce-template-file-within-a-plugin/
I am including the solution here in case the post is every removed for some reason:
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;
}
You have to override WooCommerce Template
woocommerce/templates/checkout/review-order.php and Put this file in your theme folder themes/yourthemename/woocommerce/checkout/review-order.php

Add custom javascript to Woocommerce edit product page

how can I reference a custom js-file only to the Woocommerce edit / add product page?
Thanks in advance.
Ciao
This worked for me (to be added in themes's functions.php file):
//wholesale-prices
function add_admin_scripts( $hook ) {
global $post;
if ( $hook == 'post-new.php' || $hook == 'post.php' ) {
if ( 'product' === $post->post_type ) {
wp_enqueue_script( 'myscript', get_stylesheet_directory_uri().'/js/wholesale-prices.js' );
}
}
}
add_action( 'admin_enqueue_scripts', 'add_admin_scripts', 10, 1 );

WordPress SEO plugin only visible to specific user

I am using the Yoast SEO plugin in WordPress and wanted to know if there was a way to make it only visible to one specific user in the db or in the functions.php file? Not a role, an actual user.
I tried an universal solution to simply add "plugin-name" and disable it, but failed.
But, to show WPSEO only to a specific user (ID equals 2), the following works:
add_action( 'plugins_loaded', 'seo_so_25654837' );
function seo_so_25654837()
{
if ( '2' == get_current_user_id() )
return;
remove_action( 'plugins_loaded', 'wpseo_admin_init', 15 );
}
Don't add the code to functions.php, use it as a normal plugin.
The following is also needed to remove the SEO menu from the admin bar:
add_action( 'wp_before_admin_bar_render', 'bar_so_25654837' );
function bar_so_25654837()
{
if ( '2' == get_current_user_id() )
return;
global $wp_admin_bar;
$nodes = $wp_admin_bar->get_nodes();
foreach( $nodes as $node )
{
if( !$node->parent )
{
if( 'wpseo-menu' === $node->id )
$wp_admin_bar->remove_menu( $node->id );
}
}
}
You can hook to pre_current_active_plugins to remove elements from the table before it is displayed. Using get_current_user_id() within the function will let you selectively hide a plugin.
function hide_plugins_by_user( $all_plugins=false ) {
global $wp_list_table;
// if the current user ID is not 1, hide it.
if ( 1 != get_current_user_id() ){
// the active plugins from the table
$plugins = $wp_list_table->items;
// loop through them
foreach ( $plugins as $key => $val ) {
// use the dir + filename of the plugin to hide
if ( $key == 'plugindir/plugin.php' ) {
unset( $wp_list_table->items[$key] );
}
}
}
}
add_action( 'pre_current_active_plugins', 'hide_plugins_by_user' );
This code is working fine (Credits goes to Hislop):
// Returns true if user has specific role
function check_user_role( $role, $user_id = null ) {
if ( is_numeric( $user_id ) )
$user = get_userdata( $user_id );
else
$user = wp_get_current_user();
if ( empty( $user ) )
return false;
return in_array( $role, (array) $user->roles );
}
// Disable WordPress SEO meta box for all roles other than administrator and seo
function wpse_init(){
if( !(check_user_role('seo') || check_user_role('administrator')) ){
// Remove page analysis columns from post lists, also SEO status on post editor
add_filter('wpseo_use_page_analysis', '__return_false');
// Remove Yoast meta boxes
add_action('add_meta_boxes', 'disable_seo_metabox', 100000);
}
}
add_action('init', 'wpse_init');
function disable_seo_metabox(){
remove_meta_box('wpseo_meta', 'post', 'normal');
remove_meta_box('wpseo_meta', 'page', 'normal');
}
Just place it in the functions.php file.
To disable the Yoast for all the users and enable it for just for few or specific, just add the following piece of code to your function.php file.
function remove_wpseo(){
/* if you want to keep it enabled for user with id 2 */
if ( '2' == get_current_user_id() ) {
return;
}
global $wpseo_front;
if(defined($wpseo_front)){
remove_action('wp_head',array($wpseo_front,'head'),1);
}
else {
$wp_thing = WPSEO_Frontend::get_instance();
remove_action('wp_head',array($wp_thing,'head'),1);
}
}
add_action('template_redirect','remove_wpseo');
Reference: https://makersbyte.com/disable-yoast-seo-plugin-specific-page/

wordpress show only media user has uploaded in wp_editor

I'm creating a wordpress site where the registered user has the ability to create his own post via wp_editor() on the frontend, but just one post.
Now I want to restrict the user to be able to only see his uploaded media. I use the following script in the functions.php, which works in the backend. So if a user goes to the media section in the backend he will only see his uploaded media.
But if the user goes to "insert media" pop-up on the frontend wp_editor he can still see the uploaded media from all the users.
function restricted_media_view( $wp_query ) {
if ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/upload.php' ) !== false
|| strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php' ) !== false ) {
if ( !current_user_can( 'level_5' ) ) {
global $current_user;
$wp_query->set( 'author', $current_user->id );
}
}
}
add_filter('parse_query', 'restricted_media_view' );
Do you have any idea hot to solve this annoyance? Thank you!
You might try this plugin: http://wordpress.org/extend/plugins/view-own-posts-media-only/
Alternatively try this:
add_action('pre_get_posts','ml_restrict_media_library');
function ml_restrict_media_library( $wp_query_obj ) {
global $current_user, $pagenow;
if( !is_a( $current_user, 'WP_User') )
return;
if( 'admin-ajax.php' != $pagenow || $_REQUEST['action'] != 'query-attachments' )
return;
if( !current_user_can('manage_media_library') )
$wp_query_obj->set('author', $current_user->ID );
return;
}
Source: http://wpsnipp.com/index.php/functions-php/restricting-users-to-view-only-media-library-items-they-upload/#comment-810649773
alternatively since WordPress 3.7
add_filter( 'ajax_query_attachments_args', "user_restrict_media_library" );
function user_restrict_media_library( $query ) {
global $current_user;
$query['author'] = $current_user->ID ;
return $query;
}
I use API/Filter Reference/ajax query attachments args for WP 4.3.1 and works
add_filter( 'ajax_query_attachments_args', 'show_current_user_attachments', 10, 1 );
function show_current_user_attachments( $query = array() ) {
$user_id = get_current_user_id();
if( $user_id ) {
$query['author'] = $user_id;
}
return $query;
}
just add on functions.php
or check this link WP Codex

Make *ALL* Wordpress Categories use their Parent Category Template

I want to change the default template hierarchy behavior, and force all subcategory level pages that don't have their own category template file to refer to their parent category template file. In my other post, Richard M. gave an excellent answer that solved the problem for an individual subcategory. Does anyone know how to abstract it?
function myTemplateSelect()
{
if (is_category()) {
if (is_category(get_cat_id('projects')) || cat_is_ancestor_of(get_cat_id('projects'), get_query_var('cat'))) {
load_template(TEMPLATEPATH . '/category-projects.php');
exit;
}
}
}
add_action('template_redirect', 'myTemplateSelect');
Thanks in advance.
/**
* Iterate up current category hierarchy until a template is found.
*
* #link http://stackoverflow.com/a/3120150/247223
*/
function so_3119961_load_cat_parent_template( $template ) {
if ( basename( $template ) === 'category.php' ) { // No custom template for this specific term, let's find it's parent
$term = get_queried_object();
while ( $term->parent ) {
$term = get_category( $term->parent );
if ( ! $term || is_wp_error( $term ) )
break; // No valid parent
if ( $_template = locate_template( "category-{$term->slug}.php" ) ) {
// Found ya! Let's override $template and get outta here
$template = $_template;
break;
}
}
}
return $template;
}
add_filter( 'category_template', 'so_3119961_load_cat_parent_template' );
This loops up the parent hierarchy until an immediate template is found.
i was wondering how to do the same thing for heirarchical taxonomies. TheDeadMedic's answer seems to work in that case too w/ a few tweaks:
function load_tax_parent_template() {
global $wp_query;
if (!$wp_query->is_tax)
return true; // saves a bit of nesting
// get current category object
$tax = $wp_query->get_queried_object();
// trace back the parent hierarchy and locate a template
while ($tax && !is_wp_error($tax)) {
$template = STYLESHEETPATH . "/taxonomy-{$tax->slug}.php";
if (file_exists($template)) {
load_template($template);
exit;
}
$tax = $tax->parent ? get_term($tax->parent, $tax->taxonomy) : false;
}
}
add_action('template_redirect', 'load_tax_parent_template');
The TEMPLATEPATH variable might not work for child themes - looks in parent theme folder.
Use STYLESHEETPATH instead. e.g.
$template = STYLESHEETPATH . "/category-{$cat->slug}.php";

Resources