Plugin Data Scrubbing #10

Open
HabariImporter opened this Issue Jun 27, 2011 · 12 comments

Comments

Projects
None yet
4 participants

Initially reported by: @chrismeller as #TRAC346
Often (mainly in WP-land) one will, after several years, have thousands of entries in their options table. Most of these options are left over from plugins long since deactivated.

The common opinion seems to be that, upon deactivation, a plugin should delete anything it added during its lifetime. For options and configuration data this is no major loss and can easily be re-created, should the user need.

While working on the plugin directory plugin, I was uncertain how far to take this approach. On deactivation, should it delete all plugin directory entries? That could be a lot of data (read: thousands of custom posts) to be lost accidentally.

After a discussion in IRC, it seems the best idea may be to add a 'delete data' checkbox when deactivating a plugin. This would sorta emulate the Drupal deactivate vs. uninstall functionality.

For bonus points, allowing the plugin to specify (somehow) that this box should or should not be present would eliminate some extra confusion and allow plugin authors ultimate control of what happens with their data.

Author: @freakerz
Could we do a "clean plugin options" for all current options/plugins on top of that checkbox?

Not sure how it could work, but we can surely find a way.

Author: @arickmann
I proposed a system for another platform which allowed the plugin author to register the assets the plugin was going to use, i.e. files, options, new database tables, etc, when it was first installed.

The idea being that the plugin could be uninstalled by the system instead of relying on the plugin to trigger it.

If assets have been registered then an uninstall link can be added beneath deactivate that would uninstall and deactivate.

I think this is a little more seamless than a checkbox.

Author: @freakerz
arickmann, that is what was discussed further on in IRC... can you elaborate on how you achieved this?

Author: @arickmann
Replying to [comment:5 freakerz]:

arickmann, that is what was discussed further on in IRC... can you elaborate on how you achieved this?

What I did was really pretty basic. I created a function, register_plugin_assets, that accepted the plugin file name, an array of tables, an array of options, and a callback.

A subsequent function added the option to uninstall the plugin to the action list if the plugin was deactivated and called a script that would either remove all the assets, or call reactivate the plugin, call the callback function, and deactivate it again.

Author: @michaeltwofish
Replying to [comment:6 arickmann]:

What I did was really pretty basic. I created a function, register_plugin_assets, that accepted the plugin file name, an array of tables, an array of options, and a callback.

A subsequent function added the option to uninstall the plugin to the action list if the plugin was deactivated and called a script that would either remove all the assets, or call reactivate the plugin, call the callback function, and deactivate it again.

I like this idea. If an active plugin's directory is deleted, the plugin page could have an option to clean its assets, instead of just leaving it in the active list forever, waiting for it to return.

Author: @lildude
If and when this gets implemented, it needs to be implemented for themes too as they too can store options and themes will definitely lead to DB bloat.

With the change implemented in r5022, theme previews now save options to the DB too.

Member

lildude commented Aug 22, 2011

Another method we could implement for this would be to encourage, and possible enforce, that plugins and themes always store their options be preceding the defined option name with the class name used by the plugin.

A lot of plugins already store all options using something like

$ui->append( 'checkbox', 'myoption', __CLASS__ . '__myoption', _t( 'This is my option' ) );

So I don't think much more work would be needed other than changing peoples behaviour and a few plugins. We could then implement code which could check the existence of __CLASS__ options against the currently installed plugins and themes and then offer the admin the various purge options etc.

Owner

michaeltwofish commented Dec 15, 2011

Some thoughts. Possibly should write to the database instead of using the cache.

Well-behaved addons implement the following, where assets could be files, database tables, options, etc:

private $assets = array(__CLASS__ => array(
    'files' => array('list', 'of', 'files'),
    'db_tables' => array('table')
));

public function filter_addon_assets($assets) {
  return array_merge($assets, $this->assets);
}   

On plugin init we do the following (psuedocode-ish):

$assets = Plugins::filter('addon_assets', array());
$cached = Cache::get('addon_assets');
$deleted = array();
foreach ($cached as $addon => $cache) {
  // Check if the addon is no longer announcing assets (may have been deleted)
  if (!array_key_exists($addon, $assets))
    $deleted[$addon] = $cache;
  // Find released assets (assets previously but no longer referred to) 
  $released[$addon] = $cache - $assets[$addon];
}   

// store $released, a daily Cron job will remove the assets
// store $deleted, users with permission will be asked if they want to clean the assets

// Refresh the cache
Cache::set('addon_assets', $assets);

On the plugins and themes pages, we add 'clean' to the dropdown (not delete or uninstall unless we're actually going to remove the files). In Pluggable we add (psuedocode-ish):

public static clean($addon) {
  // Check the type somehow. Maybe pass in a flag?.
  // Deactivate the addon if it's active
  // Remove its registered assets
  $cached = Cache::get('addon_assets');
  $cache = $cached[$addon];
  // Delete files
  // Drop tables
  // Remove options
  // Do whatever else you have to do
}   
Owner

michaeltwofish commented Dec 18, 2011

@ringmaster expressed some concern that the garbage collection was done with Cron rather than a specific action. I didn't get to ask him what specific action he meant though.

@ghost ghost assigned michaeltwofish Dec 29, 2011

Owner

michaeltwofish commented Aug 28, 2012

There's a branch for this, but I ran out of ergs. https://github.com/habari/system/tree/%2310

Contributor

Konzertheld commented Feb 13, 2013

@chrismeller initially was concerned what to do with posts a plugin created. That made me think of another thing that comes up every now and then: When a plugin that provides a custom content type is deactivated, what should happen to the posts of that type? I would definitely not want to have them deleted automatically.

@Konzertheld Konzertheld added this to the 1.0 milestone Mar 29, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment