11.5. WordPress Plugin Uninstall

In the previous blogs, we customized activation and deactivation phases for the plugin. In this tutorial, we use uninstall phase to clean up the entities created by the plugin.

When a plugin is uninstalled, it is already in deactivated state and it means that WordPress Action framework is no longer usable with in the plugin code. WordPress do provide a uninstall hook register_uninstall_hook(), but when when a plugin can not be written without running code within the plugin there is another mechanism to handle uninstall. When uninstall is in progress, WordPress looks for a file named named uninstall.php in plugins’ top directory and if exists, it executes it as part of uninstall phase. In Share on Social Plugin, we use unistall.php instead of uninstall hook.

When plugin uninstall is initiated by the admin, WordPress sets a constant WP_UNINSTALL_PLUGIN and share-on-social/uninstall.php checks whether this constant is defined and if so, then proceeds to call uninstall function sos_uninstall_sos_plugin().

share-on-social/uninstall.php

if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit();
}

sos_uninstall_sos_plugin();

The uninstall function calls functions to delete custom posts of type sos and to delete plugin options. If site is multisite and user is super admin then it call these functions for all sites in the network otherwise it calls the functions for the site. There is no code to handle uninstall by non super admins in multisite installation, as site admins are any way not allowed to install and uninstall plugins at site level.

 
 

share-on-social/uninstall.php

function sos_uninstall_sos_plugin () {
    if ( function_exists( 'is_multisite' ) && is_multisite() ) {
        if ( false == is_super_admin() ) {
            return;
        }
        $blogs = wp_get_sites();
        foreach ( $blogs as $blog ) {
            switch_to_blog( $blog<a href="http://codex.wordpress.org/Class_Reference/WP_Query" target="_blank"> 'blog_id' ] );
            sos_delete_sos_posts();
            sos_delete_sos_options();
            restore_current_blog();
        }
    } else {
        if ( ! current_user_can( 'activate_plugins' ) ) {
            return;
        }
        sos_delete_sos_posts();
        sos_delete_sos_options();
    }
}

Once Share on Social plugin is deactivated, its custom post type sos no longer registered but posts of that type may still exist in wp_posts table. In sos_delete_sos_posts(), we use WordPress function [WP_Query() to fetch all posts of type sos and delete them, one by one, using wp_delete_post().

share-on-social/uninstall.php

function sos_delete_sos_posts () {

    // in multisite uninstall, wp_delete_post access post_type_object and to
    // avoid access on non object we register sos post type

    register_post_type( 'sos' );

    // fetch posts of type sos
    $args = array(
            'post_type' => 'sos'
    );
    
    $query = new WP_Query( $args );
    while ($query->have_posts()) {
        $query->the_post();
        if ( 'sos' == get_post_type() ) {
            $post_id = get_the_ID();
            wp_delete_post( $post_id, true );
        }
    }
    wp_reset_postdata();
}

In multisite installation, wp_delete_post() internally uses post_type object and it will thrown an exception when it is unable to find sos custom type. To overcome this, we temporarily re-register sos custom post type and then proceed with deletion to avoid warnings in debug.log file.

 
 

The next chapter explains the nitty-gritty of WordPress Plugin unit testing.