Display selected BACS account from matching order item meta value using Woocommerce hooks

37
March 15, 2019, at 11:40 PM

Based on "Select BACS account to show in thankyou page in WooCommerce" answer code to one of my questions, I have changed the Woocommerce core file "class-wc-gateway-bacs.php" In order to select the correct bank account displayed on thankyou page, that matches with the variation attribute of a purchased product.

I have added the next code to "class-wc-gateway-bacs.php" after line 255:

foreach ( $order->get_items() as $item ) {$sede = $item->get_meta("pa_sede");};
if ( $bacs_account->sort_code != $sede ) { continue; };

So the modified code section from bank_details() function, results as follows:

        foreach ( $bacs_accounts as $bacs_account ) {
            $bacs_account = (object) $bacs_account;
            foreach ( $order->get_items() as $item ) {$sede = $item->get_meta("pa_sede");};
            if ( $bacs_account->sort_code != $sede ) { continue; };
            if ( $bacs_account->account_name ) {
                $account_html .= '<h3 class="wc-bacs-bank-details-account-name">' . wp_kses_post( wp_unslash( $bacs_account->account_name ) ) . ':</h3>' . PHP_EOL;
            }
            $account_html .= '<ul class="wc-bacs-bank-details order_details bacs_details">' . PHP_EOL;
            // BACS account fields shown on the thanks page and in emails.
            $account_fields = apply_filters(
                'woocommerce_bacs_account_fields',
                array(
                    'bank_name'      => array(
                        'label' => __( 'Bank', 'woocommerce' ),
                        'value' => $bacs_account->bank_name,
                    ),
                    'account_number' => array(
                        'label' => __( 'Account number', 'woocommerce' ),
                        'value' => $bacs_account->account_number,
                    ),
                    'sort_code'      => array(
                        'label' => $sortcode,
                        'value' => $bacs_account->sort_code,
                    ),
                    'iban'           => array(
                        'label' => __( 'IBAN', 'woocommerce' ),
                        'value' => $bacs_account->iban,
                    ),
                    'bic'            => array(
                        'label' => __( 'BIC', 'woocommerce' ),
                        'value' => $bacs_account->bic,
                    ),
                ),
                $order_id
            );
            foreach ( $account_fields as $field_key => $field ) {
                if ( ! empty( $field['value'] ) ) {
                    $account_html .= '<li class="' . esc_attr( $field_key ) . '">' . wp_kses_post( $field['label'] ) . ': <strong>' . wp_kses_post( wptexturize( $field['value'] ) ) . '</strong></li>' . PHP_EOL;
                    $has_details   = true;
                }
            }
            $account_html .= '</ul>';
        }

However, Is not a good practice and I would like to use a hooked function in the instead of messing with class-wc-gateway-bacs.php.

Any help will be appreciated.

Answer 1

The following hooked function will avoid overwriting Woocommerce class-wc-gateway-bacs.php core file, using a specific variation attribute value from order items to display the matching bank account(s) in Woocommerce Order received page (thankyou):

add_filter( 'woocommerce_bacs_accounts', 'filter_woocommerce_bacs_accounts_callback', 10, 1 );
function filter_woocommerce_bacs_accounts_callback( $bacs_accounts ){
    if ( empty($bacs_accounts) ) {
        return $bacs_accounts; // Exit
    }
    if( is_wc_endpoint_url('order-received') ) {
        $endpoint = 'order-received';
    } elseif( is_wc_endpoint_url('view-order') ) {
        $endpoint = 'view-order';
    } else {
        return $bacs_accounts; // Exit
    }
    // Get the WC_Order Object
    $order = wc_get_order( get_query_var($endpoint) );
    $sort_codes = []; // Initializing variable array
    // Loop through order items
    foreach ( $order->get_items() as $item ) {
        $sort_codes[] = $item->get_meta("pa_sede");
    }
    if ( empty($sort_codes) ) {
        return $bacs_accounts; // Exit
    }
    // Loop through Bacs accounts
    foreach ( $bacs_accounts as $key => $bacs_account ) {
        $bacs_account = (object) $bacs_account;
        // Remove the non matching bank accounts
        if ( ! in_array($bacs_account->sort_code, $sort_codes ) ) {
            unset($bacs_accounts[$key]);
        }
    }
    return $bacs_accounts;
}

Code goes in function.php file of your active child theme (or active theme). Tested and work (it should work with your product attribute for variation pa_sede).

READ ALSO
SQL: How do I filter (WHERE) a joined (ON) table in SQL?

SQL: How do I filter (WHERE) a joined (ON) table in SQL?

I have two tables (users and posts) and I want to write out all posts (among other things) by one userI'm thinking I should use a JOIN and WHERE but I get an error for using WHERE

9
Why SQLSTATE[HY000] [2002] No such file or directory Magento

Why SQLSTATE[HY000] [2002] No such file or directory Magento

When I run php bin/magento install:setup I received this error:

18
php variable as a XML string returning false when trying to put in json format to read

php variable as a XML string returning false when trying to put in json format to read

I am reading emails and getting the body of message in a variable called $messageThe variable is receiving a XML string like this:

33