Удаление плагина

Если ваш плагин записывает какие-либо данные куда угодно: в опции, базу данных, файлы и т.д., то при полном удалении плагина логично удалить и все данные, которые относятся только к нему, чтобы они не лежали мертвым грузом.

Процесс удаления плагина запускается, когда пользователь отключил плагин, а затем нажал на ссылку «Удалить» в админ-панеле на странице плагинов.

Неопытные разработчики иногда делают ошибку, используя хук деактивации плагина для удаления его данных отовсюду. Это неправильно - при деактивации должны удаляться (очищаться) только временные данные, а все данные - только при удалении плагина.

Выглядит это примерно так:

Сценарий деактивация удаление
Удаление опций из таблицы wp_options нет да
Очистка кэша да нет

Кроме того, обратите внимание, что когда плагин удаляется, хук деактивации уже сработал... Т.е. Активный плагин всегда сначала деактивируется и только потом удаляется - невозможно удалить плагин, если он активен...

Как происходит удаление?

Перед удалением плагина (ссылка "удалить" на странице плагинов) WordPress выполняет некоторые действия, благодаря которым можно удалить все следы прибывания плагина на сайте. Преимущества использования такого подхода в том, что не нужно заботится о предупреждении пользователей об удалении следов плагина перед удалением самого плагина. Это своего рода API удаления плагинов - WordPress делает часть работы за вас...

Два способа деинсталляции плагинов

Разработчиками WordPress предусмотрено два варианта полностью удалить плагин:

  1. Создать файл uninstall.php в корневой директории плагина.

  2. Использовать функцию register_uninstall_hook() - срабатывает во время удаления плагина.

#1 Файл uninstall.php

Если во время удаления плагина WordPress найдет файл uninstall.php в его папке, то будет выполнен код этого файла. Важно: в этом случае хук деактивации работать уже не будет!

Важным моментом является обязательное использования проверки константы WP_UNINSTALL_PLUGIN в этом файле. Нужно это для обеспечения безопасности, чтобы невозможно было обратиться к этому файлу напрямую.

Файлы плагина будут удалены после того, как сработает код файла uninstall.php.

ВАЖНО! В момент срабатывания файла uninstall.php никакой код не запускается! Никакие его файлы (кроме uninstall.php) не подключаются! Поэтому любые подключения файлов, классов, определение констант нужно делать отдельно.

В этом файле нужно разместить код, который удалит все что связано с плагином: опции, таблицы БД, произвольные поля и т.д.

Этот процесс необратим!

Константа WP_UNINSTALL_PLUGIN определяется WordPress в момент удаления плагина и не будет определена, если обратиться к файлу uninstall.php напрямую.

Также, константа WP_UNINSTALL_PLUGIN будет определена только после того, как был найден файл uninstall.php в папке плагина. Она не будет установлена при использовании техники удаления плагина через хук.

Пример файла uninstall.php

<?php
/**
 * ВАЖНО! Никакие файлы плагина тут не подключаются!
 *
 * Здесь доступны только базовые функции WordPress.
 *
 * Если нужны какие-то, функции или классы плагина для удаления,
 * подключите файлы и инициализируйте нужные классы здесь.
 */
defined( 'WP_UNINSTALL_PLUGIN' ) || exit;

// Удаляем опции и все остальное.
delete_option( 'my_option' );

Пример файла uninstall.php для Multisite

uninstall.php не запускается отдельно для каждого сайта сети. Поэтому логику удаления для мультисайта нужно прописывать отдельно:

/**
 * ВАЖНО! Никакие файлы плагина тут не подключаются!
 *
 * Здесь доступны только базовые функции WordPress.
 *
 * Если нужны какие-то, функции или классы плагина для удаления,
 * подключите файлы и инициализируйте нужные классы здесь.
 */
defined( 'WP_UNINSTALL_PLUGIN' ) || exit;

if( is_multisite() ){

	$blog_ids = get_sites( [ 'fields' => 'ids' ] );

	foreach( $blog_ids as $blog_id ){
		switch_to_blog( $blog_id );

		my_plugin_uninstall();

		restore_current_blog();
	}
}
else {
	my_plugin_uninstall();
}

function my_plugin_uninstall(){

	delete_option( 'my_plugin_option' );

	// удаление других данных...
}

Дебаг при удалении плагина

Чтобы проверить как работает удаление, но при этом не удалять файлы плагина, просто добавьте в конце файла uninstall.php die(). Также можно выводить какие-либо данные, например, через print_r() или как-то еще.

Чтобы увидеть результат дебага, когда удаление плагина запущено через AJAX, откройте панель разработчика в Chrome (вкладка «Сеть» (Network)). Там при запуске AJAX можно увидеть результат запроса.

#2 Функция register_uninstall_hook()

Метод с созданием файла uninstall.php более предпочтителен, по сравнению с этим методом.

Функция register_uninstall_hook() работает иначе, чем функции активации и деактивации плагина: register_activation_hook() и register_deactivation_hook().

Когда плагин удаляется и в его каталоге нет файла uninstall.php, но в основном файле плагина прописана функция удаления register_uninstall_hook(), будет вызвана эта функция удаления плагина.

При использовании register_uninstall_hook() все действия и коды плагина должны находиться внутри функций и подключаться через хуки, т.е. никакие действия плагина не должны находиться открыто в файлах плагина, потому что иначе в процессе удаления плагина они тоже будут срабатывать и могут мешать процессу удаления.

Не рекомендуется использовать этот метод, потому что он требует четкого понимания его работы. И даже в этом случае все равно можно легко ошибиться. Но если для вашего плагина подходит только такой вариант удаления, то придерживайтесь следующих правил:

  • Нельзя запускать (инициализировать) код плагина напрямую в файле - делайте это через хук plugins_loaded или позднее.
  • Лучше использовать файл удаления unistall.php.

Пример кода деинсталляции плагина через хук:

register_uninstall_hook( __FILE__, 'my_uninstall_hook' );

function my_uninstall_hook(){
	delete_option('my_option');
}

Этот код должен находится в главном файле плагина, именно на него смотрит __FILE__. Если по каким-то причинам register_uninstall_hook() нужно поместить в другой файл плагина, то в первом параметре (вместо __FILE__), нужно указать путь до главного файла плагина.