MyBB Community Forums

Full Version: plugin upgrades
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have started using a generic cache entry that hopefully plugin authors will start to piggy back off of. In my plugins from now on, I will be including the following code:

//handle version info
$plugins->add_hook("admin_config_plugins_activate", "<plugin_name>_get_version");
$plugins->add_hook("admin_config_plugins_activate_commit", "<plugin_name>_set_version");
$plugins->add_hook("admin_config_plugins_deactivate_commit", "<plugin_name>_unset_version");

/**
 * Get plugin version from cache 
 */
function <plugin_name>_get_version() 
{
	global $cache, $plugin_versions;

    //get version from this plugin file
    $<plugin_name>_info = <plugin_name>_info();

    //load plugin version cache
    $plugin_versions = $cache->read('plugin_versions');
    if(!is_array($plugin_versions))
    {
        $plugin_versions = array();
    }
    
    //if plugin name already exists, get old version
    if(isset($plugin_versions['<plugin_name>']))
    {
        $plugin_versions['old'] = $plugin_versions['<plugin_name>'];
    }
    
    //set new version variable
    $plugin_versions['new'] = $<plugin_name>_info['version'];
}

/**
 * Set plugin version in cache 
 */
function <plugin_name>_set_version() 
{
	global $cache, $plugin_versions;
	
    //update cache to latest version regardless of activate or install
    $plugin_versions['<plugin_name>'] = $plugin_versions['new'];
    unset($plugin_verisons['old']);
    unset($plugin_verisons['new']);
    $cache->update('plugin_versions', $plugin_versions);
}

/**
 * Remove (unset) plugin version in cache 
 */
function <plugin_name>_unset_version() 
{
	global $cache, $plugin_versions, $install_uninstall;
	
    //cleanup plugin version cache if uninstalled
    if($install_uninstall)
    {
        unset($plugin_verisons['old']);
        unset($plugin_verisons['new']);
        unset($plugin_verisons['<plugin_name>']);
        $cache->update('plugin_versions', $plugin_versions);
    }
}

Basically, it will try to read a cache entry called "plugin_versions" where the key is the plugin name and the value is the version code. Obviously you need to replace <plugin_name> with the 'codename' of your plugin. This is the base filename of your plugin and the same as you would use for the _install and _info and _activate functions.

Upon start of activation (and install) the get_version function will be called via a hook.

Upon end of the activation (and install) the set_version function will be called via a hook.

Upon uninstall and not just deactivation, hence the $install_uninstall conditional, unset_version function will clear the plugin_cache of the plugin's entry, leaving all of the other plugin versions in place. Handling only uninstall allows users to deactivate and maintain the 'old' version number after overwritting the plugin file with the new version. Since uninstall should be removing all items modified by the plugin, upgrading is not an issue.

Once nice thing about this setup, is that it also adds 'old' and 'new' keys to the $plugin_versions array so the authors can compare versions and upgrade accordingly.

Can't use the existing 'plugins' cache entry as it is updated via core files and I want to avoid editing those.

Thoughts from other plugin authors?
actually I found that this is not working without some core file edits unfortunately.

the issue is that the hooks I am trying to use in the plugin are being called prior to including the plugin file so the functions do not exist at the time the ACP is trying to use them.

since the hooks are in the main body they get added upon plugin system startup, but the functions for the hooks are not available since the plugin file has not yet been included in the ACP code.

I actually think that this may be a bug, because why would you hook into your own or any other plugin before it is actually included in the system. One accesses hooks via plugins, so what cases would there be to use a hook before any plugins are included?

In \admin\modules\config\plugins.php, at or around line 339 find

	if($mybb->input['action'] == "activate")
	{
		$plugins->run_hooks("admin_config_plugins_activate");
	}
	else
	{
		$plugins->run_hooks("admin_config_plugins_deactivate");
	}

and "cut" that text and "paste" it at the now line 355 to make this work (after the require_once line)
(2010-11-27, 11:05 PM)pavemen Wrote: [ -> ]Thoughts from other plugin authors?

Nice idea in theory, but a horror in practice. You're asking plugin authors to copy code - doing so will inevitably lead to bugs spreading around, and becoming unfixable, because it'd have to be changed in all plugins that use it. Also if any of the other plugins do something wrong with that version cache, they'd mess up your own plugin's data and thus break your plugin.

This is the kind of feature that just has to be in core to be useful or some other centralized place, such as a plugin that does nothing but provide other plugins with useful helper functions.

I thought about making such a helper library once; for example my Google SEO plugin has a nice function for creating setting groups and settings, as well as updating them properly. No more messing around with the settings table if that was part of core...

I even suggested something like that be added to core sometime, to no avail; sometimes I think it's easier to write your own forum software than convice the MyBB devs of anything. Wink
i wish that the devs would take some more time to help out the more advanced plugin authors. some of this stuff is pretty basic and easy to incorporate. MyBB has a lot of nice things and I like the package overall but these little issues are irritating at times. I love plugins since I can keep core files easily updated, but there are now 7 core files I manually update before upgrading every time.

I could build a simple class for additional plugin support. Include that file, create a new object and call the appropriate functions. The class would contain most of the above code, but simplified versions of my above functions would still be needed, as well as the core file fix to resolve the issue of running hooks before any plugin file is included. see my entry at

http://dev.mybb.com/issues/1326

Concerning the issue of poor coders messing up the cache entry you are correct there, perhaps the plugin authors can use similar code, but specify their own cache name...

Another question is, how many plugins need this really? What exactly do you do in your update routine when the version number changes? Why do you need the version number in order to be able to do that?

Most plugins don't have any data (other than settings), and most plugins that do have data don't actually need the version number to update it; instead they can just as well tell by looking at the structure of their data.

For example my Google SEO plugin creates a database table mybb_googleseo. It contains the keywords URLs for threads, users, etc. If I were to change the database scheme in a new version of the plugin, I'd have to update and convert the data, similar to how the MyBB installer/upgrader does it.

However I wouldn't need to know a version number. I'd just look at the table directly and see what fields it has (and change it in the new version).

I'd do it that way because the alternative (your suggestion), is way too complicated. If version numbers and plugin updates were already a core feature (with an actual update button in the plugin manager) I'd probably use that instead without thinking about it. But since we don't have that the alternatives may be better.

The only other thing that needs updating is settings, and you don't need to know the old version number for that either; you just reflect the setting entries to what the current version of your plugin supports. At least, that's how Google SEO does it.
well, i have built some plugins that have new settings added or removed, some table changes, etc. over the course of several releases.

If I can know the current version and the new version I can run the appropriate upgrade code.

To me it is just easier than testing for every change on each install and activate function call, especially if the same item has changed more than once over time.

guess it is just a different philosophy.