Creative Filtering In WordPress Plugins

I’ve went on and on about “well-built” plugins for WordPress. As much as I’d like plugins to “filter all the things”, in reality, they never account for all use cases. One such challenge I had recently involved the WP WooCommerce Mailchimp plugin.

The Challenge

This particular project used the WooCommerce Multi-Step Checkout plugin to restructure the checkout flow, so some of the normal unhook/re-hook moving around of things in WooCommerce was a bit clunky and unpredictable.

The client wanted the Mailchimp opt-in field to appear on the first page of checkout which contained only First Name, Last Name, and Email Address. The child theme was also filtering the registration part of the checkout flow, so things were a mess.

Upon digging, I found this code in the Mailchimp plugin that dictates where the opt-in field is displayed:

$opt_in_checkbox_display_location = $this->sswcmc->opt_in_checkbox_display_location();

// Maybe add an "opt-in" field to the checkout.
$opt_in_checkbox_display_location = ! empty( $opt_in_checkbox_display_location ) ? $opt_in_checkbox_display_location : 'woocommerce_review_order_before_submit';

// Old opt-in checkbox display locations.
$old_opt_in_checkbox_display_locations = array(
    'billing' => 'woocommerce_after_checkout_billing_form',
    'order'   => 'woocommerce_review_order_before_submit',
);

// Map old billing/order checkbox display locations to new format.
if ( array_key_exists( $opt_in_checkbox_display_location, $old_opt_in_checkbox_display_locations ) ) {
    $opt_in_checkbox_display_location = $old_opt_in_checkbox_display_locations[ $opt_in_checkbox_display_location ];
}

add_action( $opt_in_checkbox_display_location, array( $this, 'maybe_add_checkout_fields' ) );

Interpreting, the plugin is using a setting – grabbed with a custom wrapper for WordPress’s get_option, $this->sswcmc->opt_in_checkbox_display_location();. This value is then used as the filter name for where to place the opt-in field.

The option_name it’s using is ss_wc_mailchimp_opt_in_checkbox_display. As a chick proof-of-concept, I updated the option value in the database to woocommerce_register_form , a value that was not available in the plugin settings. It worked beautifully.

The Code

Although this plugin doesn’t let you filter the display location at run time, we could pass any valid hook name and maybe_add_checkout_fields would be run there.

I looked to see if the settings were filterable, and I found the plugin contained this code at the very end of a get_settings method:

$settings = apply_filters( $this->namespace_prefixed( 'settings_general' ), $settings );

$this->id is just the plugin’s namespace that equates to ss_wc_mailchimp. The full hook name would be ss_wc_mailchimp_settings_general. The following code was added to the child theme’s functions.php file:

add_filter( 'ss_wc_mailchimp_settings_general', 'de_ss_wc_mailchimp_settings_general' );

function de_ss_wc_mailchimp_settings_general( $settings ) {
    for ( $i = 0; $i < sizeof( $settings ); ++$i ) {
        if ( 'ss_wc_mailchimp_opt_in_checkbox_display_location' === $settings[ $i ]['id'] ) {
            $settings[ $i ]['options']['woocommerce_register_form'] = __( 'Added By Custom Code' );
        }
    }

    return $settings;
}

Which resulted in...

Another Way To Skin The Cat

If you wanted to always have the opt-in appear in a place not selectable in the settings, the get_option call could be filtered. In this example, you could return a static value with something like this:

add_filter( 'option_ss_wc_mailchimp_opt_in_checkbox_display_location', function( $value ){
    return 'custom_hook_location';
});

I favor the first solution that gives the client more control, but this goes to show that there are several ways - some good, some not as good - to overcome challenges in WordPress.

About

Web Developer

Add Your Thoughts

Your email address will not be published. Required fields are marked *