WooCommerce override function - wordpress

I'd like to override a function in woocommerce, specifically -
woocommerce/includes/wc-cart-functions.php (the wc_cart_totals_order_total_html function).
I could edit the function directly (it outputs html that needs to be changed), but I'd prefer not to as I'll lose changes on updates.
I'm sure it's a common thing, I'm just not quite sure how to go about doing that. If I copy the function to functions.php in my theme, I get an error about re-declaring the function.

It's an old topic, but maybe I could help a bit. I had similar problem. I wanted to override currencies, and add a custom currency. The functions are in woocommerce/includes/wc-core-functions.php
function get_woocommerce_currencies() {
return array_unique(
apply_filters( 'woocommerce_currencies',
array(
The other function is:
function get_woocommerce_currency_symbol( $currency = '' ) {
if ( ! $currency ) {
$currency = get_woocommerce_currency();
}
switch ( $currency ) {
...
return apply_filters( 'woocommerce_currency_symbol', $currency_symbol, $currency );
This is the code I've put in functions.php of my child theme:
add_filter( 'woocommerce_currencies', 'add_my_currency' );
function add_my_currency( $currencies ) {
$currencies['RSD'] = __( 'Serbian dinar', 'woocommerce' );
return $currencies;
}

Related

Wordpress - Setting custom template for multiple custom post types

I was wondering if anyone knew how to set up a single template for multiple custom post types. For example - I don't want to set up multiple templates that do the exact same thing.
Code
I found the following snippet while searching and it doesn't seem to work. I have placed this in functions.php in the theme I am using.
add_filter( 'single_template', function( $template ) {
$cpt = [ 'available-properties', 'leased-sold', 'norway' ];
return in_array( get_queried_object()->post_type, $cpt, true )
? 'path/to/country-single.php'
: $template;
} );
Found the answer
This seems to work great!
add_filter( 'template_include', function( $template )
{
// your custom post types
$my_types = array( 'available-properties', 'leased-sold' );
$post_type = get_post_type();
if ( ! in_array( $post_type, $my_types ) )
return $template;
return get_stylesheet_directory() . '/page-content__projects-single.php';
});

Extending Timber

I'm using Timber for the first time, and I find that it is hard to convert my pure PHP thinking to this templating model.
What I'm confused about at the moment is using a date which is an input field, not the post date.
So I've got a repeater field from ACF. It has three sub-fields: release_date, document_file, and document_title. My release date format is YYYY-MM-DD.
As you might have guessed, this repeater field is output as a list of PDFs.
So far so good, but then I want some advanced functionality - namely, to have the PDFs display by release_date by default. I also want to be able to filter by the year, i.e. - if you click "2015", it would only show the documents from that year.
I know exactly how I would do this in straight WordPress, but I'm pretty confused making it on Timber. I've been trying to do it using a custom filter, but I have felt what I actually want is a custom class?
In addition, when I installed Timber it didn't come with the starter theme, so I did a search and downloaded one from GitHub. I've got a feeling this is a legacy version though, because the file structure and syntax doesn't seem to match the documentation.
Downloaded from here: https://github.com/timber/starter-theme
But for example this code in the starter theme functions.php:
function add_to_twig( $twig ) {
/* this is where you can add your own functions to twig */
$twig->addExtension( new Twig_Extension_StringLoader() );
$twig->addFilter('split_date', new Twig_SimpleFilter('split_date', array($this, 'split_date')));
return $twig;
}
Doesn't quite match the syntax in https://github.com/timber/timber/wiki/Extending-Timber under "Adding to Twig".
Here are a few helper functions to make it easy for me to extend timber.
function add_context_var( $key, $var ) {
add_filter( 'timber_context', function ( $context ) use ( $key, $var ) {
$context[ $key ] = $var;
return $context;
} );
}
function add_context_func( $key, $callback ) {
add_filter( 'timber/twig', function ( $twig ) use ( $key, $callback ) {
$twig->addFunction( new \Twig_SimpleFunction( $key, $callback ) );
return $twig;
} );
}
function add_to_context( $key, $val ) {
if ( is_callable( $val ) ) {
add_context_func( $key, $val );
} else {
add_context_var( $key, $val );
}
}
function add_to_context_filter( $key, $callback ) {
add_filter( 'get_twig', function ( $twig ) use ( $key, $callback ) {
$twig->addExtension( new Twig_Extension_StringLoader() );
$twig->addFilter( new Twig_SimpleFilter( $key, $callback ) );
return $twig;
} );
}
//php file
add_to_context("blue", "this key is blue")
add_to_context("red", function($extra = ""){
return "this key is red and it has $extra";
})
add_to_context_filter( "relative_link", function ( $content ) {
return str_replace( "http://", "//", $content );;
} );
//twig file
color: {{ blue }}
color: {{ red("a function parameter") }}
github: {{ "http://github.com/"|relative_link }}
//output html
color: this key is blue
color: this key is red and it has function parameter
github: //github.com/

Trying to extend a Wordpress plugin, need to hook a function

I am trying to add some site-specific functionality to the Wordpress plugin Appointments+. When a user is making an appointment, they select certain services and enter information into some fields for confirmation.
What I want to do is add some code so the extra information fields are related to which service they choose. For example, if they choose Service A, they have to fill in some information and those fields are validated. But if they choose Service B, hide the fields and skip the validation.
Here is an example of the original code:
function post_confirmation() {
...some extra stuff
$values = explode( ":", $_POST["value"] );
$location = $values[0];
$service = $values[1];
do_action('app-additional_fields-validate');
...more stuff
}
Here is the kind of thing I want to do, but not alter this original plugin file:
function post_confirmation() {
...some extra stuff
$values = explode( ":", $_POST["value"] );
$location = $values[0];
$service = $values[1];
if (($service == 1) || ($service == 3)) {
do_action('app-additional_fields-validate');
}
...more stuff
}
I admit that I am new to using hooks and filters. I want to disable/enable that action based on a variable in the function. How can I do that with another hook/filter?
Thank you.
Unhook the hook used for calling post_confirmation and override this function from your functions.php like
remove_action( 'current_action_hook', 'post_confirmation' );
add_action( 'current_Action_hook', 'post_custom_confirmation' );
function post_custom_confirmation(){
...some extra stuff
$values = explode( ":", $_POST["value"] );
$location = $values[0];
$service = $values[1];
if (($service == 1) || ($service == 3)) {
do_action('app-additional_fields-validate');
}
...more stuff
}
I think this should work, I have used this way during a woocommerce plugin development before nearly 2 months below is working code example , so that if you need any modification on code above, you can take reference .
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
add_action( 'woocommerce_checkout_order_review', 'pk_order_review', 10, 1 );
function pk_order_review($template) {
global $woocommerce;
$template = wc_get_template ( 'checkout/review-order.php', FALSE, FALSE, untrailingslashit( plugin_dir_path( __FILE__ ) ) . '/templates/');
return $template;
exit;
}
Another way you can do it is
add_action( 'app-additional_fields-validate', 'foo' );
function foo(){
if (($service == 1) || ($service == 3)) {
/* Your stuffs */
}
}
This is actually part answer, part new question. If that is possible to do here.
So, I finally found a way to affect the desired function.
The function I was trying to modify is contained in a class so, I did something like this:
class my_Check extends Appointments {
function __construct() {
$this->unregister_parent_hook();
add_action( 'wp_ajax_post_confirmation', array( $this, 'post_confirmation' ) );
add_action( 'wp_ajax_nopriv_post_confirmation', array( $this, 'post_confirmation' ) );
}
function unregister_parent_hook() {
global $appointments; //this was the object created with the parent class
remove_action( 'wp_ajax_post_confirmation', array( $appointments, 'post_confirmation' ) );
remove_action( 'wp_ajax_nopriv_post_confirmation', array( $appointments, 'post_confirmation' ) );
}
function post_confirmation() {
...do the stuff with my mods...
}
}
$new_Check = new my_Check();
Only, I have a new problem now. The parent class does a lot more in the __construct() (many 'add_action()'s, etc.). And $this is populated with a lot more data. The problem is, these other things and data do not seem to be carrying over into the child class. I tried adding a parent::__construct() in the child's __construct() function, but that did not seem to work.
The code with my mods works except for things that need more data in the $this carried over from the parent class.
How can I maintain all the parent class's variable, functions, hooks & filters, etc. into the child class?

How to customize get_the_post_navigation in theme

get_the_post_navigation() function is defined inside wp-includes/link-template.php
How can I override it in my theme?
get_the_post_navigation does not utilize any filters so there is no easy way to modify or override all of its output.
While get_the_post_navigation does not apply any filter itself, it does call functions that do apply filter. Specifically get_adjacent_post_link:
return apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post );
Hooking into that filter will allow you to override some, but not all, of the output. get_the_post_navigation also uses _navigation_markup which does not apply any filters. That portion of the output cannot be overridden.
You could request that a filter be added to that function. It would be a simple update and it would enable you to override all of the output.
function _navigation_markup( $links, $class = 'posts-navigation', $screen_reader_text = '' ) {
if ( empty( $screen_reader_text ) ) {
$screen_reader_text = __( 'Posts navigation' );
}
$template = '
<nav class="navigation %1$s" role="navigation">
<h2 class="screen-reader-text">%2$s</h2>
<div class="nav-links">%3$s</div>
</nav>';
//Add this line
$template = apply_filters('navigation_markup_template', $template);
return sprintf( $template, sanitize_html_class( $class ), esc_html( $screen_reader_text ), $links );
}
An easier solution might just be to create your own post navigation function, and then replace all references to get_the_post_navigation in your theme with your function.

remove columns from woocommerce product page

Hi I am trying to limit the options certain users have when viewing the products list within woocommerce for wordpress admin pages.
if( current_user_can('vendor') ) {
function my_columns_filter( $columns ) {
unset($columns['tags']);
unset($columns['featured']);
unset($columns['type']);
return $columns;
}
}
add_filter( 'manage_edit-product_columns', 'my_columns_filter', 10, 1 );
Any help or guidance would be much appreciated.
You're doing it wrong.
Place if/else inside the function instead of wrapping the function.
function my_columns_filter( $columns ) {
if( current_user_can('vendor') ) {
unset($columns['tags']);
unset($columns['featured']);
unset($columns['type']);
return $columns;
}
}
add_filter( 'manage_edit-product_columns', 'my_columns_filter', 10, 1 );
You are not using the correct column names, or perhaps WC has changed them since you posted your question. It also better to check if a column still exists before removing it in case WC does change their column names.
Here is a future proof solution you can past into your theme's functions.php:
function my_product_columns_filter( $columns ) {
if ( current_user_can( 'vendor' ) ) {
foreach ( array( 'product_tag', 'featured', 'product_type' ) as $name ) {
if ( isset( $columns[ $name ] ) ) {
unset( $columns[ $name ] );
}
}
}
return $columns;
}
add_filter( 'manage_edit-product_columns', 'my_product_columns_filter' );
no coding solution
If you're just looking for a quick solution without the need for coding, you could use the free admin columns plugin from wordpress.org, which allows you to add and remove columns with a few clicks.

Resources