WP: Prevent automatic removing of directories on update

wordpress plugin development, advanced topics, wp api, hooks

Every WP Plugin developers knows this issue: you have some subdirectories in your WP plugin and they are removed by wordpress on each update. I’ve got this problem with Zanmantou and Cryptex too. I found some solutions but they are all using recursive, inperformant “copy” functions to fullfill the task – the much better solution is to move the specified directories out of the the plugin directory before update and move them back after the finished update! (the php function rename is the equivalent to unix mv/move)

Cryptex’ Updater Class#

This is my current solution, an simple updater class. You can register the directories you want to be preserved from update – that’s it.

Example Plugin structure:

  • cryptex
    • cache
    • lang
    • fonts
    • class

Task: the cache directorie should be preserved on update

Usage#

// insert this code into your plugin main/boot file - "cryptex" is the prefix for backuped folders
$updater = new Cryptex_Updater('cryptex');

// it's required! to use absolute pathes
$updater->register(CRYPTEX_PLUGIN_PATH.DIRECTORY_SEPARATOR.'fonts');
$updater->register(CRYPTEX_PLUGIN_PATH.DIRECTORY_SEPARATOR.'cache');

Updater Class#

class Cryptex_Updater{
// folders to restore
private $_restoreFolders;
private $_prefix = '';

public function __construct($prefix, $restoreFolders=array()){
// store informations
$this->_restoreFolders = $restoreFolders;
$this->_prefix = $prefix;

// update/install events - well they are called on upgrading ANY plugin..
// but at this moment there is no better way..
add_action('upgrader_pre_install', array($this, 'updateBackup'), 10, 0);
add_action('upgrader_post_install', array($this, 'updateRestore'), 10, 0);
}

public function register($dir){
$this->_restoreFolders[] = $dir;
}

public function updateBackup(){
foreach ($this->_restoreFolders as $folder){
// move files outside the plugin direcotry
rename($folder, WP_PLUGIN_DIR.DIRECTORY_SEPARATOR.$this->_prefix.'_backup_'.sha1($folder));
}
}

public function updateRestore(){
foreach ($this->_restoreFolders as $folder){
// delete the NEW folder first -> problem on windows systems...
if (is_dir($folder)){
rmdir($folder);
}

// move folder back
rename(WP_PLUGIN_DIR.DIRECTORY_SEPARATOR.$this->_prefix.'_backup_'.sha1($folder), $folder);
}
}
}

Disadvantages#

This solution has one main issue: the WP hooks get triggered on updating EVERY plugin…at the moment i didn’t know any way to prevent it, because the hook upgrader_pre_install does not provide any informations about the current-updated plugin (upgrader_post_install does it..). Normally this is not a real problem, but on install/update errors it could “damage” the directories you which should be preserved.. (in this case you can fix it manually by going into the wp-content/plugin directory and moving the directories back into the plugin directories). I hope this will be fixed/added in the future by WordPress.

Attached Files#