WooCommerce add to cart URL

To add WooCommerce product into cart you can achieve via the following query parameters:

Solution thanks to https://wordpress.stackexchange.com/a/159390/33599

In source code at https://github.com/woocommerce/woocommerce/blob/d6e5c7e3b8a17e1e5a17defda208eb3b95b18891/includes/class-wc-form-handler.php#L715

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)

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' );

 

Get currency rates from ECB

For a WooCommerce powered site I needed a currency rate fetching function so here is what I used.

/**
 * Get currency rate
 *
 * Info @ http://www.ecb.int/stats/exchange/eurofxref/html/index.en.html
 * The reference rates are usually updated by 3 pm CET
 * cron: 0 17 * * 1,2,3,4,5
 *
 * @param   string  Currency code name
 * @return  float
 **/
function wi_get_currency_rate( $currency = 'CZK' ) {

    if ( false === ( $currencies = get_transient( 'wi_currency_rates' ) ) ) {

        $currencies = array();
        $xml = wp_remote_get( 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',
            array( 'user-agent' => 'WordPress' )
        );

        $xml = simplexml_load_string( $xml['body'] );
        foreach( $xml->Cube->Cube->Cube as $cube )
            $currencies[ $cube->attributes()->currency ] = (float) $cube->attributes()->rate;

        set_transient( 'wi_currency_rates', $currencies, 23 * HOUR_IN_SECONDS );
    }


    return $currencies[ $currency ];

}

Converting gettext .po files to binary .mo files via command line

Updated a WP plugin and translation needed fixation. I edited the .po file, but no change was on the site. I needed to convert it to .mo file.
Thanks to Joss Crowcroft and his post http://www.josscrowcroft.com/2011/code/php-mo-convert-gettext-po-file-to-binary-mo-file-php/ I was able to convert.

$ msgfmt -cv -o wp-content/plugins/woocommerce/i18n/languages/woocommerce-sk_SK.mo wp-content/plugins/woocommerce/i18n/languages/woocommerce-sk_SK.po
1939 translated messages, 2 untranslated messages.

WooCommerce advanced (product attribute) search

I couldn’t find answers why Googling, how to make search work with product attributes of WooCommerce products.
Wrote the code, but it was always 404 page. URLs with /taxonomy/term_slug (example.com/radius/16/) were working, but example.com/?s=&post_type=product&pa_radius=TERM_ID&pa_width=TERM_ID&pa_manufacturer=TERM_ID wasn’t outputing any products.

header.php

 <form action="<?php echo site_url( '/' ); ?>" class="search2">
 <input type="hidden" name="s" value=""/>
 <input type="hidden" name="post_type" value="product"/>
 <img src="<?php echo get_template_directory_uri(); ?>/img/box_holder.png">

 <div class="search_box">
 <h3 class="search_title">Search by attribute</h3>
 <select class="selectBox" name="pa_season">
 <?php echo pf_get_filter_options( 'Season', 'pa_season' ); ?>
 </select>
 <select class="selectBox" name="pa_radius">
 <?php echo pf_get_filter_options( 'Radius', 'pa_radius' ); ?>
 </select>
 <select class="selectBox" name="pa_height">
 <?php echo pf_get_filter_options( 'Height', 'pa_height' ); ?>
 </select>
 <select class="selectBox" name="pa_width">
 <?php echo pf_get_filter_options( 'Width', 'pa_width' ); ?>
 </select>
 <select class="selectBox" name="pa_speedindex">
 <?php echo pf_get_filter_options( 'Speed index', 'pa_speedindex' ); ?>
 </select>
 <select class="selectBox" name="pa_manufacturer">
 <?php echo pf_get_filter_options( 'Manufacturer', 'pa_manufacturer' ); ?>
 </select>
 <button class="search-button" type="submit">Search ➤</button>
 </div>
 </form>

functions.php

/**
 * Output for specified taxonomy ( product attributee)
 *
 * @return string  list
 */
function pf_get_filter_options( $title, $taxonomy ) {

    global $wp_query;

    $options = '' . $title . '';

    $data = get_terms( $taxonomy );

    foreach ( $data as $term ) {

        // Skip some weird terms
        switch ( $taxonomy ) {
            case 'pa_radius':
                if ( in_array($term->slug, array('13c','14c','15c','1616c','16c')) )
                    continue( 2 );

                break;

            case 'pa_width':
                if ( in_array($term->slug, array('195205','255265')) )
                    continue( 2 );

                break;
        }

        $selected = isset( $wp_query->query_vars[$taxonomy] ) && $wp_query->query_vars[$taxonomy] == $term->term_id ? ' selected="selected"' : '';
        $options .= '<option value="' . $term->term_id . '"' . $selected . '>' . $term->name . '</option>';

    }

    return $options;

}

So I decided to watch https://www.youtube.com/watch?v=v7Uj3pLQseM to free my mind a bit.
In the talk Debug Bar was mentioned that I tried before, but I’m used
to watch errors in OSX Console.app so I wasn’t using Debug Bar.

What catched my attention was the SQL queries log so I added
define('SAVEQUERIES', true); to my wp-config.php and installed Debug Bar
to give it another try.

So I clicked Debug, went over the queries and found the solution.

Debug Bar Queries
Debug Bar Queries

Solution

The problem was that as value I was using $term->term_id instead $term->slug by which the queries search in code.

Different wp_title and WooCommerce page title by terms

In a project I needed wp_title with the separator, but WC page title without separator for specific terms of a taxonomy.

Here’s the code I used:

/**
 * Add more descriptive page title to some taxonomy term
 *
 * @param string $title    Page title.
 * @param string $sep      Title separator.
 * @return string
 **/
function pf_fix_title( $title, $sep = null ) {

    $term = get_queried_object();

    if ( is_front_page() && $sep !== null )
        return "Lacné letné a zimné pneumatiky $sep";
    if (is_404() && $sep !== null )
        return "Stránka neexistuje $sep";

    switch ( $term->taxonomy ) {

        case 'pa_radius':
            $title = "$term->name-palcové pneumatiky $sep";
            break;

        case 'pa_season':
            $tax = get_taxonomy( $term->taxonomy );
            $title = "$term->name pneumatiky $sep";
            if ( $sep !== null )
                $title .= " $tax->label $sep";
            break;

    }

    return $title;
}
add_filter( 'wp_title', 'pf_fix_title', 10, 2 );
add_filter( 'woocommerce_page_title', 'pf_fix_title' );