WordPress - Do Something When A Plugin or Theme Updates

Recently, I was faced with an unavoidable situation where I had to alter a third-party plugin’s code. The plugin is one I consider a “well-made” plugin, incorporating apply_filters or do_action all over the place. However, the hooks weren’t available in a specific spot where I needed them for a project.

Of course, the downside of altering third-party plugin or theme code is maintainability. Every time the plugin or theme releases an update, the custom code must be reintegrated manually once the upgrades are complete. So, tracking when a plugin or theme is updated becomes important.

A Nasty Choice

The plugin I had to alter was actually the ShipStation Integration1Full disclosure, this is a affiliate link, and I make money if you make any purchases on WooCommerce.com after visiting this URL., made available by WooCommerce.com. As part of a recent Warehouse Operations application I built, a key component was identifying inventory locations. ShipStation allows for a Location field for each order item, according to the documentation, but the WooCommerce plugin doesn’t provide this value in its XML export.

The challenge was to find a way to include the Location field in the export. However, as mentioned, there’s not an apply_filters available to alter the export XML. The only option currently available to remedy this is to alter the plugin code directly.2I’ve actually submitted a ticket to ask the developers if more hooks can be added to help this situation. I’ve yet to hear anything back, but will update this article if/when I do.

The Problem

Editing plugin or theme files directly is never a good idea. If you do, any time the item updates in the future, the altered code will be overwritten. This creates some debt by requiring a developer to reintegrate the customizations after the updates are complete.

Knowing when updates occur is usually an easy thing to keep up with because, prior to WordPress 5.5, plugin and theme updates were a manual process by default. However, 5.5 introduces automatic updates for plugins and themes in core, and there’s now a possibility for unattended updates.

With this possibility, we need a reliable way to determine when a specific plugin or theme is updated, even when we, as the developer, aren’t involved.

The Solution

WordPress core doesn’t provide a specific hooks for our purposes, like plugin_updated or theme_updated. Yet.3I’ve asked the Core Team to consider adding hooks such as these, given the increased use cases now that unattended, automatic updates are part of core. The ones that are available are more generic, and they are: upgrader_pre_install, pre_auto_update, upgrader_process_complete, and upgrader_post_install. The one of particular import in our use-case is upgrader_process_complete.

The upgrader_process_complete action fires when the entire upgrader process is complete for all items. However, with the second argument, $hook_extra, we can gather some information about what was updated. Printing out the entire $hook_extra array results in something like this:

Lucky for us, $hook_extra['plugins'], if available, will give us relative paths of plugins that were just successfully updated. We just need to filter through the values to determine whether a specific plugin was updated. Example:

add_action( 'upgrader_process_complete', 'de_upgrader_process_complete', 10, 2 );

function de_upgrader_process_complete( $upgrader_object, $options ) {
    $shipstation_updated = false;

    if ( isset( $options['plugins'] ) && is_array( $options['plugins'] ) ) {
        foreach ( $options['plugins'] as $index => $plugin ) {
            if ( 'woocommerce-shipstation-integration/woocommerce-shipstation.php' === $plugin ) {
                $shipstation_updated = true;
                break;
            }
        }
    }

    if ( ! $shipstation_updated ) {
        return;
    }

    // Do something when ShipStation plugin has been updated.
}

We’re checking for $hook_extra['plugins']‘s existence and looping through it to find our specific plugin. If we do, we update a flag. After a quick “bail” check on the flag, we can run whatever code we need to when the ShipStation plugin has been updated.

In my case, I’d like to have an email sent to me to alert me that the plugin has been updated. Since I’m running this code on three sites, I’d like that email to tell me which site as well. Here’s the final code:

add_action( 'upgrader_process_complete', 'de_upgrader_process_complete', 10, 2 );

function de_upgrader_process_complete( $upgrader_object, $options ) {
    $site = get_bloginfo( 'name' );
    $shipstation_updated = false;

    if ( isset( $options['plugins'] ) && is_array( $options['plugins'] ) ) {
        foreach ( $options['plugins'] as $index => $plugin ) {
            if ( 'woocommerce-shipstation-integration/woocommerce-shipstation.php' === $plugin ) {
                $shipstation_updated = true;
                break;
            }
        }
    }

    if ( ! $shipstation_updated ) {
        return;
    }

    $subject = sprintf(
        __( '%s ShipStation Plugin Updated' ),
        $site
    );

    $message = sprintf(
        __( 'The ShipStation plugin on %s has been updated.' ),
        $site
    );

    wp_mail( 'david@dream[dash]encode[dot]com', $subject, $message );
}

Fell free to customize this code to fit your needs. You could set a transient that triggers an admin notice. You could disable the plugin automatically until you get a change to reapply your customizations. There’s a lot of possibilities here.

You can also use similar code to parse $hook_extra['themes'] to detect when a specific theme is updated. The output is similar in that it’s a list of paths relative to wp-content/themes/.

If you do find this code helpful, leave me a comment letting me know!

About

Web Developer

Add Your Thoughts

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