user379888
user379888

Reputation:

Overriding a function in WordPress

I am trying to override a WooCommerce function load_country_states(). I am creating a custom WordPress plugin to do it. I read in some answers that one can't simply override a function in PHP. Whats the best way to rewrite a function defined in WordPress theme/plugin in a plugin? I have read this.

The function to modify:

/**
 * Load the states.
 */
public function load_country_states() {
    global $states;

    // States set to array() are blank i.e. the country has no use for the state field.
    $states = array(
        'AF' => array(),
        'AT' => array(),
        'AX' => array(),
        'BE' => array(),
        'BI' => array(),
        'CZ' => array(),
        'DE' => array(),
        'DK' => array(),
        'EE' => array(),
        'FI' => array(),
        'FR' => array(),
        'IS' => array(),
        'IL' => array(),
        'KR' => array(),
        'NL' => array(),
        'NO' => array(),
        'PL' => array(),
        'PT' => array(),
        'SG' => array(),
        'SK' => array(),
        'SI' => array(),
        'LK' => array(),
        'SE' => array(),
        'VN' => array(),
    );

    // Load only the state files the shop owner wants/needs.
    $allowed = array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() );

    if ( ! empty( $allowed ) ) {
        foreach ( $allowed as $code => $country ) {
            if ( ! isset( $states[ $code ] ) && file_exists( WC()->plugin_path() . '/i18n/states/' . $code . '.php' ) ) {
                include( WC()->plugin_path() . '/i18n/states/' . $code . '.php' );
            }
        }
    }

    $this->states = apply_filters( 'woocommerce_states', $states );
}

After modification it should work like:

/**
 * Load the states.
 */
public function load_country_states() {
    global $states;
    // Load only the state files the shop owner wants/needs.
    $allowed = array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() );

    if ( ! empty( $allowed ) ) {
        foreach ( $allowed as $code => $country ) {
            if ( ! isset( $states[ $code ] ) && file_exists( WC()->plugin_path() . '/i18n/states/' . $code . '.php' ) ) {
                include( WC()->plugin_path() . '/i18n/states/' . $code . '.php' );
            }
        }
    }

    $this->states = apply_filters( 'woocommerce_states', $states );
}

Upvotes: 2

Views: 1701

Answers (2)

user379888
user379888

Reputation:

I tried to read up more about this and came up with this solution that worked. We can use WordPress filter to add hack into specific events. I modified the code and it now works.

    /**
     * Load the states.
     */
function load_country_states_modified() {
        global $states;
        // Load only the state files the shop owner wants/needs.
        $foobar = new WC_Countries;  // correct
        $allowed = array_merge( $foobar->get_allowed_countries(), $foobar->get_shipping_countries() );
        if ( ! empty( $allowed ) ) {
            foreach ( $allowed as $code => $country ) {
                if ( ! isset( $states[ $code ] ) && file_exists( WC()->plugin_path() . '/i18n/states/' . $code . '.php' ) ) {
                    include( WC()->plugin_path() . '/i18n/states/' . $code . '.php' );
                }
            }
        }

        //$this->states = apply_filters( 'woocommerce_states', $states );
    }
    add_filter( 'woocommerce_states', 'load_country_states_modified' );

Upvotes: 0

Felipe Elia
Felipe Elia

Reputation: 1418

Actually you can't simply override a function. It's only possible if it's surrounded by a if ( ! function_exists() ) conditional. In your case it seems to be a class method and to override it (in plain PHP) you should extend the class and override the method. In your WordPress scenario it's simpler, because you can use a simple filter. Your code should be like:

public function so48005823_load_country_states( $states ) {
    // make your magic here and 
    // don't forget to return the $states var

    return $states;
}
add_filter( 'woocommerce_states', 'so48005823_load_country_states' );

Make sure to not simple copy/paste the code, because the $this variable is only available inside the class scope. You can put this function into a simple plugin and it'll start working.

Hope it helps!

Upvotes: 1

Related Questions