Override Avada Catalog sorting hook back to defaul

2020-07-27 02:34发布

问题:

I am trying to modify Woocommerce sorting option to get a customized one by adding the following code to Avada child function.php file:

    // add custom sorting option 
   add_filter( 'woocommerce_get_catalog_ordering_args', 
  'custom_woocommerce_get_catalog_ordering_args' );

  function custom_woocommerce_get_catalog_ordering_args( $args ) {
  $orderby_value = isset( $_GET['orderby'] ) ? woocommerce_clean( 
  $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', 
  get_option( 'woocommerce_default_catalog_orderby' ) );

  if ( 'random_list' == $orderby_value ) {
 $args['orderby'] = 'menu_order Date';
    $args['order'] = 'ASC';
    $args['meta_key'] = '';
    }

return $args;
}

add_filter( 'woocommerce_default_catalog_orderby_options', 
'custom_woocommerce_catalog_orderby' );
 add_filter( 'woocommerce_catalog_orderby', 
 'custom_woocommerce_catalog_orderby' );

 function custom_woocommerce_catalog_orderby( $sortby ) {
$sortby['random_list'] = 'Menu_order_date';
return $sortby;
}
//end custom ordering code 

this code work fine if i didn't enable WooCommerce Shop Page Ordering Boxes and actually i wanted the ordering box to be displayed on my shop page and product category, so i contact Avada Support for this issue and it turn out Avada use thier own hook for WooCommerce Shop Page Ordering Boxes with the following code:

/**
 * Controls the actions adding the ordering boxes.
 *
 * @access public
 * @since 5.0.4
 * @param object $query The main query.
 * @return void
 */
public function product_ordering( $query ) {

    // We only want to affect the main query.
    if ( ! $query->is_main_query() || $query->is_search() ) {
        return;
    }

    if ( $query->get( 'page_id' ) ) {
        $page_id = absint( $query->get( 'page_id' ) );
    } else {
        $page_id = absint( Avada()->fusion_library->get_page_id() );
    }

    if ( wc_get_page_id( 'shop' ) === $page_id || $query->is_post_type_archive( 'product' ) || $query->is_tax( get_object_taxonomies( 'product' ) ) ) {

        if ( Avada()->settings->get( 'woocommerce_avada_ordering' ) ) {
            remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
            add_action( 'woocommerce_before_shop_loop', array( $this, 'catalog_ordering' ), 30 );

            add_action( 'woocommerce_get_catalog_ordering_args', array( $this, 'get_catalog_ordering_args' ), 20 );
        }
    }
}

Avada Support said I can remove Avada function from this hook and add my own using child theme.

 add_action( 'woocommerce_get_catalog_ordering_args', array( $this, 
'get_catalog_ordering_args' ), 20 );

I searched all over the interent seeking help and I found many pepole asked about almost same question but without answer.

if anyone could help removing avada function that will be very helpful for me and other pepole who's looking for that as well.

How I can remove Avada hooked function from woocommerce_get_catalog_ordering_args action hook?

after several test i disocoverd the following code which added by Avada team as follow:

/**
 * Modified the ordering of products.
 *
 * @access public
 * @since 5.1.0
 */
public function catalog_ordering() {
    get_template_part( 'templates/wc-catalog-ordering' );
}

/**
 * Gets the catalogue ordering arguments.
 *
 * @access public
 * @since 5.1.0
 * @param array $args The arguments.
 * @return array
 */
function get_catalog_ordering_args( $args ) {
    global $woocommerce;
    $woo_default_catalog_orderby = get_option( 'woocommerce_default_catalog_orderby' );

    // Get the query args.
    if ( isset( $_SERVER['QUERY_STRING'] ) ) {
        parse_str( sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ), $params );
    }

    // Get order by.
    $pob = ( ! empty( $params['product_orderby'] ) ) ? $params['product_orderby'] : $woo_default_catalog_orderby;

    // Get order.
    $po = 'asc';
    if ( isset( $params['product_order'] ) ) {
        // Dedicated ordering.
        $po = $params['product_order'];
    } else {
        // Get the correct default order.
        $po = 'asc';
        if ( 'date' === $pob || 'popularity' === $pob || 'rating' === $pob || 'price-desc' === $pob ) {
            $po = 'desc';
        }
    }

    // Remove posts_clause filter, if default ordering is set to rating or popularity to make custom ordering work correctly.
    if ( 'default' !== $pob ) {
        if ( 'popularity' === $woo_default_catalog_orderby || 'rating' === $woo_default_catalog_orderby ) {
            WC()->query->remove_ordering_args();
        }
    }

    $orderby  = 'date';
    $order    = strtoupper( $po );
    $meta_key = '';

    switch ( $pob ) {
        case 'menu_order':
        case 'default':
            $orderby  = $args['orderby'];
            break;
        case 'date':
            $orderby  = 'date';
            break;
        case 'price':
        case 'price-desc':
            add_filter( 'posts_clauses', array( $this, 'order_by_price_post_clauses' ) );
            add_action( 'wp', array( $this, 'remove_ordering_args_filters' ) );
            break;
        case 'popularity':
            $meta_key = 'total_sales';
            add_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) );
            add_action( 'wp', array( $this, 'remove_ordering_args_filters' ) );
            break;
        case 'rating':
            $meta_key = '_wc_average_rating';
            $orderby  = array(
                'meta_value_num' => strtoupper( $po ),
                'ID'             => 'ASC',
            );
            break;
        case 'name':
            $orderby  = 'title';
            break;
    }

    $args['orderby']  = $orderby;
    $args['order']    = $order;
    $args['meta_key'] = $meta_key;

    return $args;
}

if i just modify the following:

    // Remove posts_clause filter, if default ordering is set to rating or popularity to make custom ordering work correctly.
    if ( 'default' !== $pob ) {
        if ( 'popularity' === $woo_default_catalog_orderby || 'rating' === $woo_default_catalog_orderby ) {
            WC()->query->remove_ordering_args();
        }
    }

    $orderby  = 'date';
    $order    = strtoupper( $po );
    $meta_key = '';

to

    // Remove posts_clause filter, if default ordering is set to rating or popularity to make custom ordering work correctly.
    if ( 'default' !== $pob ) {
        if ( 'popularity' === $woo_default_catalog_orderby || 'rating' === $woo_default_catalog_orderby ) {
            WC()->query->remove_ordering_args();
        }
    }

    $orderby  = 'menu_order Date';
    $order    = strtoupper( $po );
    $meta_key = '';

$orderby = 'menu_order Date'; instead of $orderby = 'date';

it's simply am forcing the avada to use my own custom ordering instead of date.

but that not really practical solution as i modified class-avada-woocommerce.php

is there any suggestion to do find solution by add some code to avada child them instead

回答1:

Update 2:

I think that if you add a highest priority than Avada's theme hook it will work (here I have set it to 100), and the only change to do in this function is $args['orderby'] = 'menu_order date'; to get the similar change you have done on Avada's files.

The code:

add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_catalog_ordering_args', 100 );
function custom_woocommerce_get_catalog_ordering_args( $args ) {
    $args['orderby'] = 'menu_order date';
    return $args;
}

This code goes in function.php file of your active child theme.

It should work


The very strange thing is that woocommerce_get_catalog_ordering_args is a filter hook, but NOT an action hook (so I have changed my code)…

Then something is wrong in the Avada's theme code and you should report it to the support.

You just need to increase your hooked function, so it will override Avada's:

add_action('after_setup_theme', 'remove_avada_function' );
function remove_avada_function(){
    remove_action( 'woocommerce_before_shop_loop', 'catalog_ordering', 30 );
    add_action( 'woocommerce_before_shop_loop', 'custom_catalog_ordering', 30 );
}


回答2:

There is nothing wrong with the Avada Code.

Avada intentionally unhooks the filter 'woocommerce_get_catalog_ordering_args' and writes its own filter "catalog_ordering" in '/wp-content/themes/Avada/includes/class-avada-woocommerce.php'

That calls

'/wp-content/themes/Avada/templates/wc-catalog-ordering.php'

Please overwrite the template by using your child theme and copying the contents of wc-catalog-ordering.php.

i.e. "/wp-content/themes/Avada-Child-Theme/templates/wc-catalog-ordering.php"

You'll be able to handle the orders however you'd like once complete.

Previously mentioned, the function "remove_avada_function" is hooked on 'after_setup_theme' and is used to remove the hook. However since 'remove_avada_function' is called before the action 'pre_get_post' is called, 'remove_avada_function' won't remove the action that does not currently exist.

Happy Coding