MyBB Community Forums

Full Version: [Suggestion] Plugin version cache
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

I have some ideas for the upgrade process of plugins.

How about a functionality that caches the version of installed plugins?
I think, that would be helpful for developers, to write upgrade routines.

Here is an example plugin, to illustrate what I mean.
<?php
if (!defined('IN_MYBB'))
{
	if (headers_sent() === false) header('HTTP/1.1 403 Forbidden');

	exit();
}

/**
 * test_info
 *
 * @return array Information about the plugin
 */
function test_info()
{
	return array(
	 'name' => 'Test',
	 'description' => 'A sample plugin.',
	 'website' => '',
	 'author' => 'Cayo',
	 'authorsite' => 'http://community.mybb.com/user-30686.html',
	 'version' => '1.0.X',
	 'guid' => '',
	 'compatibility' => '16*'
	);
}

/**
 * test_install
 *
 * @global pluginSystem $plugins
 * @return void
 */
function test_install()
{
	global $plugins;

	// <Installation stuff>

	// Write the current version into the cache
	$plugins->setVersion('test', '1.0.0');
}

/**
 * test_is_installed
 *
 * @global MyLanguage $lang
 * @global pluginSystem $plugins
 * @return boolean True if installed, otherwise false
 */
function test_is_installed()
{
	global $lang, $plugins;

	// <Checking tables, fields etc>

	// Get the cached version
	$strVersion = $plugins->getVersion('test');
	if (is_string($strVersion)) return true;

	return false;
}

/**
 * test_uninstall
 *
 * @global pluginSystem $plugins
 * @return void
 */
function test_uninstall()
{
	global $plugins;

	// <Uninstall stuff>

	// Remove the plugin from the version cache
	$plugins->removeVersion('test');
}

/**
 * test_activate
 *
 * @global boolean $installed
 * @global string $message
 * @global pluginSystem $plugins
 * @return void
 */
function test_activate()
{
	global $installed, $message, $plugins;

	// <Activation stuff>

	if ($installed == true)
	{
		// Get the cached version
		$strVersion = $plugins->getVersion('test');

		// Upgrade from v1.0.0 to v1.0.1
		if ($strVersion == '1.0.0')
		{
			// <Upgrade stuff>

			// Write the new version into the cache
			$plugins->setVersion('test', '1.0.1');

			$message = 'The selected plugin has been upgraded (to v1.0.1) and activated successfully.';
			flash_message($message, 'success');
		}
		// Upgrade from v1.0.1 to v1.0.2
		elseif ($strVersion == '1.0.1')
		{
			// <Upgrade stuff>

			// Write the new version into the cache
			$plugins->setVersion('test', '1.0.2');

			$message = 'The selected plugin has been upgraded (to v1.0.2) and activated successfully.';
			flash_message($message, 'success');
		}
		// ...
	}
}
?>

So the plugin will know,
- whether a new version was uploaded
- which version was installed previously

The users only have to deactivate the plugin and upload the new files.
Upon the next activation, the plugin checks whether upgrading is necessary.
As you can see, the upgrade process depends on the previous installed version.

The implementation (extending the pluginSystem class) would be quite easy.
	/** @var array */
	private $arrVersionCache = null;

	/**
	 * getVersion
	 *
	 * @global datacache $cache
	 * @param string $strPlugin
	 * @return mixed Version on success, false on error, otherwise null
	 */
	public function getVersion($strPlugin)
	{
		// The cache hasn't been loaded yet
		if ($this->arrVersionCache === null)
		{
			global $cache;

			$this->arrVersionCache = $cache->read('plugins_version');
		}

		// The cache hasn't been loaded successfully
		if ($this->arrVersionCache === false)
		{
			return false;
		}

		if (isset($this->arrVersionCache[$strPlugin]))
		{
			return $this->arrVersionCache[$strPlugin];
		}

		return null;
	}

	/**
	 * setVersion
	 *
	 * @global datacache $cache
	 * @param string $strPlugin
	 * @param string $strVersion
	 * @return boolean True on success, otherwise false
	 */
	public function setVersion($strPlugin, $strVersion)
	{
		global $cache;

		// The cache hasn't been loaded yet
		if ($this->arrVersionCache === null)
		{
			$this->arrVersionCache = $cache->read('plugins_version');
		}

		$this->arrVersionCache[$strPlugin] = $strVersion;

		$cache->update('plugins_version', $this->arrVersionCache);

		return true;
	}

	/**
	 * removeVersion
	 *
	 * @global datacache $cache
	 * @param string $strPlugin
	 * @return boolean True on success, otherwise false
	 */
	public function removeVersion($strPlugin)
	{
		global $cache;

		// The cache hasn't been loaded yet
		if ($this->arrVersionCache === null)
		{
			$this->arrVersionCache = $cache->read('plugins_version');
		}

		if (isset($this->arrVersionCache[$strPlugin]))
		{
			unset($this->arrVersionCache[$strPlugin]);
			$cache->update('plugins_version', $this->arrVersionCache);

			return true;
		}

		return false;
	}

So that's my idea - I hope my explanation was understandable Wink
And of course, maybe it is interesting only for the larger plugins.

However, what do you think about it?
I've done this for MySupport. When you deactivate it caches the old version, then when you upload the new file, there's steps for the upgrade process; when you activate it sees what your old version was and runs any necessary upgrade steps.

Would be very good if this was natively supported in 2.0 though, does make things very easy.
I think the number of plugins which need this is very close to 0... and the number of developers who could use it correctly is probably even lower than that. Smile

If you really must do this, you already can without modification on MyBB's end... the cache system allows the creation of new custom entries so you can store version numbers there.
Please, don't worry about the implementation und the way of usage.
I used it as example, how it could work. That doesn't mean, it's final Wink

I think it would also possible, to implement it like the other "default functions".

// This is already a "default function"
function test_install()
{
  // <Installation stuff>

  // Return the current version (pluginSystem will write it into the cache)
  return CURRENT_VERSION;
}

// This could be a new "default function"
// If the current version != the cached version, this function,
// is called by the pluginSystem upon the next activation
function test_upgrade($strCachedVersion)
{
  // <Upgrade stuff>

  // Return the current version (pluginSystem will write it into the cache)
  return CURRENT_VERSION;
}

I think, this wouldn't be difficult to use, for the most developers Wink

And of course, the plugins can use their own cache for their upgrade process.
But in my Opinion, it would be much better, to use just one cache for those things.