Custom sorting for WooCommerce products order by

I had to really customize the order by of the main WP query. Finally looks like I nailed it.


function pn_woocommerce_product_query( WP_Query $wp_query ) {
if ( $wp_query->get( 'orderby' ) == 'menu_order title' ) {
$wp_query->set( 'meta_query', [
'relation' => 'AND',
'internal_stock' => [
'key' => '_manage_stock',
'compare' => 'EXIST',
],
'stock_status' => [
'key' => '_stock_status',
'compare' => 'EXIST',
],
'price' => [
'key' => '_price',
'compare' => 'EXISTS',
],
] );
$wp_query->set( 'orderby', [
'internal_stock' => 'ASC',
'stock_status' => 'ASC',
'price' => 'ASC',
] );
}
}
add_action( 'woocommerce_product_query', 'pn_woocommerce_product_query' );
function pn_posts_orderby_request( $orderby ) {
// Output based on pn_woocommerce_product_query()
if ( $orderby == 'CAST(pn_postmeta.meta_value AS CHAR) ASC, CAST(mt1.meta_value AS CHAR) ASC, CAST(mt2.meta_value AS CHAR) ASC' ) {
$orderby = "pn_postmeta.meta_value ASC, FIELD (mt1.meta_value, 'instock', '3days', 'outofstock'), mt2.meta_value ASC";
}
return $orderby;
}

SQL to get WooCommerce product categories (terms)

For an import script I needed to get WooCommerce product categories so I ended up looking the generated query in /var/log/mysql/query.log for get_the_terms($postID, ‘taxonomy_name’)

I ended up using the following SQL query to get product categories:

SELECT t.*, tt.*
FROM wp_terms AS t 
INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id 
INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id
WHERE tt.taxonomy IN ('product_cat') AND tr.object_id IN (11448)

Change locale for WooCommerce email

To change WooCommerce email language you need to change the locale after order submit.

Using $_GET might be dirty, but works 🙂


<?php
/**
* Plugin Name: Slovak WooCommerce emails
* Plugin URI: https://www.nevilleweb.sk/
* Description: Send only slovak WooCommerce emails
* Version: 1.0.0
* Author: Michal Zuber
* Author URI: https://nevilleweb.sk/
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly.
}
add_filter('plugin_locale', 'custom_locale', 10, 2);
function custom_locale($locale, $domain)
{
if ('woocommerce' == $domain && isset($_GET['wc-ajax']) && $_GET['wc-ajax'] == 'checkout') {
return 'sk_SK';
}
return $locale;
}

WooCommerce email with custom total row

To add a custom total row to woocommerce email total section just hook into woocommerce_get_order_item_totals

Customise order total rows

add_filter('woocommerce_get_order_item_totals', 'my_woocommerce_get_order_item_totals', 10, 2);
function my_woocommerce_get_order_item_totals($total_rows, $order)
{
    $new_total_rows['cart_subtotal'] = $total_rows['cart_subtotal'];

    $new_total_rows['shipping'] = array(
        'label' => 'Slovak Parcel Service:',
        'value' => wc_price(3),
    );

    $gateway = wc_get_payment_gateway_by_order($order);
    if ('cod' == $gateway->id) {
        $new_total_rows['cod'] = array(
            'label' => 'Cash on delivery:',
            'value' => wc_price(1),
        );
    }

    $new_total_rows['order_total'] = $total_rows['order_total'];

    return $new_total_rows;
}

WooCommerce check if product in cart is in stock

Check if product in cart is in stock:

foreach (WC()->cart->cart_contents as $item) {
    $product_id = isset($item['variation_id']) ? $item['variation_id'] : $item['product_id'];
    $product = new \WC_Product_Factory();
    $product = $product->get_product($product_id);
    if ($item['quantity'] > $product->get_stock_quantity()) {
        $inStock = false;
        break;
    }
}

Fix language of WooCommerce ‘Thank You’ redirect URL for qTranslate

I struggled a bit with wrong translation of the thank you page. For translation I used qTranslate and IM8 qTranslate WooCommerce

Looking at the Network tab in Chrome I saw the 301 redirect, but it took a while to figure out that a missing slash (/) was doing that wrong redirect.

Screen Shot 2014-10-19 at 9.37.36 AM Screen Shot 2014-10-19 at 9.37.49 AM
I added the following to functions.php to fix the issue:

/**
 * Add slash before question mark due 301 redirect that prevents the lang query to pass
 *
 **/
function atc_payment_successful_result( $result ) {

 $result['redirect'] = str_replace( '?lang', '/?lang', $result['redirect'] );
 return $result;
}
add_filter( 'im8qtranslatewoocommerce_payment_redirect_filters', '__return_empty_array' ); // Prevent plugin filter
add_filter( 'woocommerce_payment_successful_result', 'atc_payment_successful_result' );

 

Add manufacturer category to WooCommerce product from post title

I had to categorize more than 4000 WooCommerce products (car tyres) which contained manufacturer name as first word in title. So did it with the following code:

/**
 * Add manufacturer product category to WooCommerce product from post title
 *
 * @return void
 */
function pf_add_manufacturer_cat() {

    // Get manufacturer from product title
    for ($i = 1; $i < 6; $i++) {

        $args = array(
            'post_type' => 'product',
            'posts_per_page' => 1000,
            'page' => $i,
        );
        $products = new WP_Query( $args );
        while ( $products->have_posts() ) {
            $products->the_post();

            // First word of title is manufacturer
            $terms = explode( ' ', get_the_title() );

            // Append cat
            $term = term_exists( $terms[0], 'product_cat');
            if ( $term['term_id'] > 0 ) {
                wp_set_post_terms( get_the_ID(), $term['term_id'], 'product_cat', true );
            }
        }

    }

}
add_action( 'init', 'pf_add_manufacturer_cat' );

Documentation for the used function http://codex.wordpress.org/Function_Reference/wp_set_post_terms

Add manufacturer tag to WooCommerce product from title

I had to tag more than 4000 products so I came up with the following WP action:

/**
 * Add manufacturer product_tag to WooCommerce product from post title
 *
 * @return void
 **/
function mz_add_manufacturer_tag() {

    // Get manufacturer from product title
    for ($i = 1; $i < 6; $i++) {
        $args = array(
            'post_type' => 'product',
            'posts_per_page' => 1000,
            'page' => $i,
        );
        $products = new WP_Query( $args );
        while ( $products->have_posts() ) {
            $products->the_post();

            // First word of title is manufacturer
            $terms = explode( ' ', get_the_title() );

            // Append tag
            if ( ! has_term( $terms[0], 'product_tag' ) ) {
                wp_set_post_terms( get_the_ID(), $terms[0], 'product_tag', true );
            }
        }

    }

}
add_action( 'init', 'mz_add_manufacturer_tag' );

Show WooCommerce product count in theme

Couldn’t Google the solution so after some time a came up with the following solution:

// functions.php
function my_product_count() {
    $product_count = 0;

    // Get count for all product categories
    foreach (get_terms('product_cat') as $term)
        $product_count += $term->count;

    return $product_count;
}
<!-- header.php -->
<div class="counter">
    <span><?php echo my_product_count() ?><br>products</span>
</div>