upgrader_process_completeaction-hookWP 3.6.0

Fires when an upgrader finishes. It can be used to perform an action after a plugin, theme, WordPress core, or language pack update.

The hook fires after the updated module's files have already been replaced. When a plugin is updated, for example, it fires after the plugin files have been updated.

This hook does not have to be registered early. It can be used in a theme's functions.php file, for example.

Usage

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

/**
 * Function for `upgrader_process_complete` action-hook.
 * 
 * @param WP_Upgrader $upgrader   WP_Upgrader instance. In other contexts this might be a Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
 * @param array       $hook_extra Array of bulk item update data.
 *
 * @return void
 */
function wp_kama_upgrader_process_complete_action( $upgrader, $hook_extra ){

	// action...
}
$this(WP_Upgrader)

A WP_Upgrader instance.

Depending on the operation, it can be one of these objects:

$hook_extra(array)

Data about the item being updated.

  • action(string)
    Event type.
    Default: 'update'

  • type(string)
    Update process type. Possible values: plugin, theme, translation, or core.

  • bulk(true/false)
    Whether this is a bulk update process.
    Default: true

  • plugins(array)
    Paths to the main plugin files, relative to the plugins directory.

  • themes(array)
    Theme slugs.

  • translations(array)
    Translation data.

    • language(string)
      Translation locale.

    • type(string)
      Translation type. Possible values: plugin, theme, or core.

    • slug(string)
      Translation text domain: the theme/plugin slug, or default for core translations.

    • version(string)
      Theme, plugin, or core version.

Examples

#1 Plugin update and the data received by the hook

Update Query Monitor from version 3.3.2 to 3.3.3 and write the hook variables to __upgrader_process_complete_info.txt in the site root.

// Upgrade test
add_action( 'upgrader_process_complete', 'my_upgrate_function', 10, 2);
function my_upgrate_function( $upgrader_object, $hook_extra ){

	$put  = '';
	$put .= '$upgrader_object = '. print_r( $upgrader_object, 1 ) ."\n\n\n";
	$put .= '$hook_extra = '. print_r( $hook_extra, 1 ) ."\n\n\n";

	foreach( $hook_extra['plugins'] as $plugin_rel_path ){

		$data = get_plugin_data( WP_PLUGIN_DIR ."/$plugin_rel_path" );

		$put .= "$plugin_rel_path data = ". print_r( $data, 1 ) ."\n\n\n";
	}

	file_put_contents( "{$_SERVER['DOCUMENT_ROOT']}/__upgrader_process_complete_info.txt", $put );

}

The resulting __upgrader_process_complete_info.txt file contains the following data from inside the hook callback:

$upgrader_object = Plugin_Upgrader Object (
	[result] => Array (
			[source] => C:/sites/example.com/www/wp-content/upgrade/query-monitor.3.3.3-VlQkjR/query-monitor/
			[source_files] => Array (
					[0] => assets
					[1] => classes
					[2] => collectors
					[3] => composer.json
					[4] => dispatchers
					[5] => LICENSE
					[6] => output
					[7] => query-monitor.php
					[8] => readme.txt
					[9] => wp-content
				)

			[destination]        => C:\sites\example.com\www/wp-content/plugins/query-monitor/
			[destination_name]   => query-monitor
			[local_destination]  => C:\sites\example.com\www/wp-content/plugins
			[remote_destination] => C:/sites/example.com/www/wp-content/plugins/query-monitor/
			[clear_destination]  => 1
		)

	[bulk] => 1
	[strings] => Array (
			[bad_request]          => Invalid data provided.
			[fs_unavailable]       => Could not access filesystem.
			[fs_error]             => Filesystem error.
			[fs_no_root_dir]       => Unable to locate WordPress root directory.
			[fs_no_content_dir]    => Unable to locate WordPress content directory (wp-content).
			[fs_no_plugins_dir]    => Unable to locate WordPress plugin directory.
			[fs_no_themes_dir]     => Unable to locate WordPress theme directory.
			[fs_no_folder]         => Unable to locate needed folder (%s).
			[download_failed]      => Download failed.
			[installing_package]   => Installing the latest version…
			[no_files]             => The package contains no files.
			[folder_exists]        => Destination folder already exists.
			[mkdir_failed]         => Could not create directory.
			[incompatible_archive] => The package could not be installed.
			[files_not_writable]   => The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.
			[maintenance_start]    => Enabling Maintenance mode…
			[maintenance_end]      => Disabling Maintenance mode…
			[up_to_date]           => The plugin is at the latest version.
			[no_package]            => Update package not available.
			[downloading_package]  => Downloading update from <span class="code">%s</span>…
			[unpack_package]       => Unpacking the update…
			[remove_old]           => Removing the old version of the plugin…
			[remove_old_failed]    => Could not remove the old plugin.
			[process_failed]       => Plugin update failed.
			[process_success]      => Plugin updated successfully.
			[process_bulk_success] => Plugins updated successfully.
		)

	[skin] => WP_Ajax_Upgrader_Skin Object (

			[errors:protected] => WP_Error Object (
					[errors] => Array (
						)

					[error_data] => Array (
						)
				)

			[messages:protected] => Array (
					[0] => Enabling Maintenance mode…
					[1] => Downloading update from https://downloads.wordpress.org/plugin/query-monitor.3.3.3.zip…
					[2] => Unpacking the update…
					[3] => Installing the latest version…
					[4] => Removing the old version of the plugin…
					[5] => Plugin updated successfully.
					[6] => Disabling Maintenance mode…
				)

			[upgrader]    => Plugin_Upgrader Object *RECURSION*
			[done_header] =>
			[done_footer] =>
			[result]      => Array (
					[source]       => C:/sites/example.com/www/wp-content/upgrade/query-monitor.3.3.3-VlQkjR/query-monitor/
					[source_files] => Array (
							[0] => assets
							[1] => classes
							[2] => collectors
							[3] => composer.json
							[4] => dispatchers
							[5] => LICENSE
							[6] => output
							[7] => query-monitor.php
							[8] => readme.txt
							[9] => wp-content
						)

					[destination]        => C:\sites\example.com\www/wp-content/plugins/query-monitor/
					[destination_name]   => query-monitor
					[local_destination]  => C:\sites\example.com\www/wp-content/plugins
					[remote_destination] => C:/sites/example.com/www/wp-content/plugins/query-monitor/
					[clear_destination]  => 1
				)

			[options] => Array (
					[url] =>
					[nonce] =>
					[title] =>
					[context] => C:\sites\example.com\www/wp-content
				)

			[plugin_info] => Array (
					[Name]        => Query Monitor
					[PluginURI]   => https://querymonitor.com/
					[Version]     => 3.3.2
					[Description] => The Developer Tools Panel for WordPress.
					[Author]      => John Blackbourn
					[AuthorURI]   => https://querymonitor.com/
					[TextDomain]  => query-monitor
					[DomainPath]  => /languages/
					[Network]     =>
					[Title]       => Query Monitor
					[AuthorName]  => John Blackbourn
				)

			[plugin_active] => 1
		)

	[update_count] => 1
	[update_current] => 1
)

$hook_extra = Array (
	[action]  => update
	[type]    => plugin
	[bulk]    => 1
	[plugins] => Array (
		[0] => query-monitor/query-monitor.php
	)
)

query-monitor/query-monitor.php file data = Array (
	[Name]        => Query Monitor
	[PluginURI]   => https://querymonitor.com/
	[Version]     => 3.3.3
	[Description] => The Developer Tools Panel for WordPress. <cite>By <a href="https://querymonitor.com/">John Blackbourn</a>.</cite>
	[Author]      => <a href="https://querymonitor.com/">John Blackbourn</a>
	[AuthorURI]   => https://querymonitor.com/
	[TextDomain]  => query-monitor
	[DomainPath]  => /languages/
	[Network]     =>
	[Title]       => <a href="https://querymonitor.com/">Query Monitor</a>
	[AuthorName]  => John Blackbourn
)

#2 Display a notice after a plugin update

This mini-plugin demonstrates how to display a notice when a plugin is updated.

It displays different admin notices (see admin_notices): one after the plugin is installed (activated), and another after the plugin is updated using the current hook.

<?php

/**
 * Plugin Name: Upgrader Process Example
 * Plugin URI:  https://catapultthemes.com/wordpress-plugin-update-hook-upgrader_process_complete/
 * Description: Just an example of using upgrader_process_complete
 * Version:     1.0.0
 * Author:      Catapult Themes
 * Author URI:  https://catapultthemes.com/
 * Text Domain: wp-upe
 * Domain Path: /languages
 */

defined( 'ABSPATH' ) || exit;

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

add_action( 'admin_notices', 'wp_upe_display_update_notice' );
add_action( 'admin_notices', 'wp_upe_display_install_notice' );

# On activation, set a transient so we know the plugin was just activated
register_activation_hook( __FILE__, function() {
	set_transient( 'wp_upe_activated', 1 );
} );

/**
 * This function runs when WordPress completes its upgrade process
 * It iterates through each plugin updated to see if ours is included
 *
 * @param array $upgrader_object
 * @param array $options
 */
function wp_upe_upgrade_completed( $upgrader_object, $options ) {

	// The path to our plugin's main file
	$our_plugin = plugin_basename( __FILE__ );

	// If an update has taken place and the updated type is plugins and the plugins element exists
	if( $options['action'] === 'update' && $options['type'] === 'plugin' && isset( $options['plugins'] ) ) {

		// Iterate through the plugins being updated and check if ours is there
		foreach( $options['plugins'] as $plugin ) {

			if( $plugin == $our_plugin ) {
				// Set a transient to record that our plugin has just been updated
				set_transient( 'wp_upe_updated', 1 );
			}
		}
	}
}

/**
 * Show a notice to anyone who has just updated this plugin
 * This notice shouldn't display to anyone who has just installed the plugin for the first time
 */
function wp_upe_display_update_notice() {

	// Check the transient to see if we've just updated the plugin
	if( get_transient( 'wp_upe_updated' ) ) {

		echo '<div class="notice notice-success"><p>' . __( 'Thanks for updating', 'wp-upe' ) . '</p></div>';

		delete_transient( 'wp_upe_updated' );
	}
}

/**
 * Show a notice to anyone who has just installed the plugin for the first time
 * This notice shouldn't display to anyone who has just updated this plugin
 */
function wp_upe_display_install_notice() {

	// Check the transient to see if we've just activated the plugin
	if( get_transient( 'wp_upe_activated' ) ) {

		echo '<div class="notice notice-success"><p>' . __( 'Thanks for installing', 'wp-upe' ) . '</p></div>';

		// Delete the transient so we don't keep displaying the activation message
		delete_transient( 'wp_upe_activated' );
	}
}

Changelog

Since 3.6.0 Introduced.
Since 3.7.0 Added to WP_Upgrader::run().
Since 4.6.0 $translations was added as a possible argument to $hook_extra.

Where the hook is called

WP_Upgrader::run()
upgrader_process_complete
Core_Upgrader::upgrade()
upgrader_process_complete
Plugin_Upgrader::bulk_upgrade()
upgrader_process_complete
Language_Pack_Upgrader::bulk_upgrade()
upgrader_process_complete
Theme_Upgrader::bulk_upgrade()
upgrader_process_complete
wp-admin/includes/class-wp-upgrader.php 988
do_action( 'upgrader_process_complete', $this, $options['hook_extra'] );
wp-admin/includes/class-core-upgrader.php 221-228
do_action(
	'upgrader_process_complete',
	$this,
	array(
		'action' => 'update',
		'type'   => 'core',
	)
);
wp-admin/includes/class-plugin-upgrader.php 412-421
do_action(
	'upgrader_process_complete',
	$this,
	array(
		'action'  => 'update',
		'type'    => 'plugin',
		'bulk'    => true,
		'plugins' => $plugins,
	)
);
wp-admin/includes/class-language-pack-upgrader.php 280-289
do_action(
	'upgrader_process_complete',
	$this,
	array(
		'action'       => 'update',
		'type'         => 'translation',
		'bulk'         => true,
		'translations' => $language_updates_results,
	)
);
wp-admin/includes/class-theme-upgrader.php 510-519
do_action(
	'upgrader_process_complete',
	$this,
	array(
		'action' => 'update',
		'type'   => 'theme',
		'bulk'   => true,
		'themes' => $themes,
	)
);

Where the hook is used in WordPress

wp-admin/includes/admin-filters.php 146
add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
wp-admin/includes/admin-filters.php 147
add_action( 'upgrader_process_complete', 'wp_version_check', 10, 0 );
wp-admin/includes/admin-filters.php 148
add_action( 'upgrader_process_complete', 'wp_update_plugins', 10, 0 );
wp-admin/includes/admin-filters.php 149
add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 );
wp-admin/includes/class-language-pack-upgrader.php 274
remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
wp-admin/includes/class-language-pack-upgrader.php 275
remove_action( 'upgrader_process_complete', 'wp_version_check' );
wp-admin/includes/class-language-pack-upgrader.php 276
remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
wp-admin/includes/class-language-pack-upgrader.php 277
remove_action( 'upgrader_process_complete', 'wp_update_themes' );
wp-admin/includes/class-language-pack-upgrader.php 292
add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
wp-admin/includes/class-language-pack-upgrader.php 293
add_action( 'upgrader_process_complete', 'wp_version_check', 10, 0 );
wp-admin/includes/class-language-pack-upgrader.php 294
add_action( 'upgrader_process_complete', 'wp_update_plugins', 10, 0 );
wp-admin/includes/class-language-pack-upgrader.php 295
add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 );
wp-admin/includes/class-plugin-upgrader.php 132
add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
wp-admin/includes/class-plugin-upgrader.php 148
remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
wp-admin/includes/class-plugin-upgrader.php 221
add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
wp-admin/includes/class-plugin-upgrader.php 244
remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
wp-admin/includes/class-theme-upgrader.php 245
add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
wp-admin/includes/class-theme-upgrader.php 261
remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
wp-admin/includes/class-theme-upgrader.php 321
add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
wp-admin/includes/class-theme-upgrader.php 343
remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
wp-admin/includes/class-wp-automatic-updater.php 662
remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
wp-admin/includes/class-wp-automatic-updater.php 663
remove_action( 'upgrader_process_complete', 'wp_version_check' );
wp-admin/includes/class-wp-automatic-updater.php 664
remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
wp-admin/includes/class-wp-automatic-updater.php 665
remove_action( 'upgrader_process_complete', 'wp_update_themes' );
wp-includes/class-wp-textdomain-registry.php 80
add_action( 'upgrader_process_complete', array( $this, 'invalidate_mo_files_cache' ), 10, 2 );