How deprecate code on WordPress Plugin

As you start to develop plugins to sell or distribute for free on the WordPress plugin repository you will see yourself in one of the worst situations as a product developer.

In order to improve your code you will need to let go of old code and introduce new stuff to the codebase.

You will face the following problem, how will you do it without breaking themes and other plugins that rely on your current code?

How to approach the deprecation of code?

You will need to warn your users about this change, if that given change is a major one you should change the version number accordingly, you can see more on how to do it using Semantic Versioning.

A very good practice is to always explain what is happening on any of the versions in the change log, which should be easy if every change that is meaningful you add a new item to a list of changes on that version.

Since your are talking about code, you should give the third party developers a warning, and give then a little bit of time before actually removing something from your codebase.

How to deprecate on WordPress

Any WordPress developer that knows what is doing should always work with the constant WP_DEBUG set to true, so that E_NOTICE or E_DEPRECATED PHP triggered errors show up on the screen or in the change log file.

We will start by warning that the developer is doing something wrong if X condition happens:

/**
 * Cloning is forbidden.
 *
 * @since 2.1
 */
public function __clone() {
    _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'woocommerce' ), '2.1' );
}

On the WooCommerce exemple above, we are warning the developer with _doing_it_wrong if he tries to clone the WC_Checkout class of the core plugin.

Arguments

It's also possible to throw a notice if you've deprecated an argument from a method or function:

/**
 * Register a setting and its sanitization callback
 *
 * @since 2.7.0
 *
 * @param string $option_group A settings group name. Should correspond to a whitelisted option key name.
 *  Default whitelisted option key names include "general," "discussion," and "reading," among others.
 * @param string $option_name The name of an option to sanitize and save.
 * @param callable $sanitize_callback A callback function that sanitizes the option's value.
 */
function register_setting( $option_group, $option_name, $sanitize_callback = '' ) {
    global $new_whitelist_options;

    if ( 'misc' == $option_group ) {
        _deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'misc' ) );
        $option_group = 'general';
    }

    if ( 'privacy' == $option_group ) {
        _deprecated_argument( __FUNCTION__, '3.5', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'privacy' ) );
        $option_group = 'reading';
    }

    $new_whitelist_options[ $option_group ][] = $option_name;
    if ( $sanitize_callback != '' )
        add_filter( "sanitize_option_{$option_name}", $sanitize_callback );
}

Now we have a WordPress core exemple of function that has 2 deprecated arguments, one was done in the version 3.0 and the other on version 3.5. The argument deprecation notice is triggered by the function _deprecated_argument.

Functions

Sometimes Most of the time, you will need to deprecate a function:

/**
 * Calculates the new dimensions for a downsampled image.
 *
 * @since 2.0.0
 * @deprecated 3.0.0
 * @deprecated Use wp_constrain_dimensions()
 * @see wp_constrain_dimensions()
 *
 * @param int $width Current width of the image
 * @param int $height Current height of the image
 * @param int $wmax Maximum wanted width
 * @param int $hmax Maximum wanted height
 * @return array Shrunk dimensions (width, height).
 */
function wp_shrink_dimensions( $width, $height, $wmax = 128, $hmax = 96 ) {
    _deprecated_function( __FUNCTION__, '3.0', 'wp_constrain_dimensions()' );
    return wp_constrain_dimensions( $width, $height, $wmax, $hmax );
}

That's an example from WordPress Core, where a simple function was deprecated using _deprecated_function and the arguments were redirected to the new function to avoid breaking code that is still using the old function.

Files

When doing major changes to the codebase you will need to move files around, and these files might be included in other plugins so you will need to keep the file and to as the following example from the WordPress Core, using _deprecated_file:

<?php
/**
 * Administration Functions
 *
 * This file is deprecated, use 'wp-admin/includes/admin.php' instead.
 *
 * @deprecated 2.5.0
 * @package WordPress
 * @subpackage Administration
 */

_deprecated_file( basename(__FILE__), '2.5', 'wp-admin/includes/admin.php' );

/** WordPress Administration API: Includes all Administration functions. */
require_once(ABSPATH . 'wp-admin/includes/admin.php');

Did I miss something?

If you have a different opinion on how this deprecation subject or if you have a question, leave a comment below.

Discussions — One Response

  • Luke March 28, 2016 on 6:31 pm

    Thanks for writing this! Very helpful. I used this article to reference deprecating a method in Stream.

    Reply

Leave a Reply