Difference between revisions of "Plugin Autoinstall"

From GeeklogWiki
Jump to: navigation, search
(added note that the autoinstall function may be called more than once)
m
 
(9 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<center>''(work in progress - scheduled for inclusion in Geeklog 1.6)''</center>
 
 
 
= Introduction =
 
= Introduction =
  
Line 28: Line 26:
  
 
Plugins that ship with an <tt>autoinstall.php</tt> file won't need to provide the "traditional" install script (<tt>admin/plugins/foo/install.php</tt>) unless they want to be backward-compatible with Geeklog releases prior to 1.6.
 
Plugins that ship with an <tt>autoinstall.php</tt> file won't need to provide the "traditional" install script (<tt>admin/plugins/foo/install.php</tt>) unless they want to be backward-compatible with Geeklog releases prior to 1.6.
 +
  
 
== plugin_autoinstall_ ==
 
== plugin_autoinstall_ ==
Line 87: Line 86:
  
 
In case of an error during the install, Geeklog will also use this information to attempt a cleanup of the database, i.e. remove groups, permissions, etc.
 
In case of an error during the install, Geeklog will also use this information to attempt a cleanup of the database, i.e. remove groups, permissions, etc.
 +
 +
=== Plugin dependencies and version control ===
 +
 +
Since Geeklog 1.8.0, a new and optional array, $requires, is available. It must contain dependency information for a plugin.
 +
You can make a requirement for a particular range of versions of Geeklog, databases and other plugins.
 +
Each dependency is stored inside this array as another array.
 +
 +
The minimal usage is as follows:
 +
<pre>
 +
...
 +
    $requires= array(
 +
        // This plugin requires another plugin, 'someplugin', and does not need a databases to function.
 +
        array('plugin' => 'someplugin')
 +
    );
 +
...
 +
</pre>
 +
 +
<pre>
 +
...
 +
    $requires= array(
 +
        // This plugin requires another plugin, 'someplugin', and supports MySQL and PgSQL databases.
 +
        array('plugin' => 'someplugin'),
 +
        array('db' => 'mysql'),
 +
        array('db' => 'pgsql')
 +
    );
 +
...
 +
</pre>
 +
 +
You can define any particular range of versions as the requirements for your plugin by adding the 'version' and 'operator' indeces to the arrays. Here's a more complex example:
 +
<pre>
 +
...
 +
 +
    $requires= array(
 +
        // This plugin requires a version greater than or equal to 1.0.0 of 'someplugin' (The default 'operator' is '>=')
 +
        array('plugin' => 'someplugin',
 +
              'version' => '1.0.0'),
 +
 +
        // This plugin also requires a version greater than 1.0.0 of 'someotherplugin'
 +
        array('plugin' => 'someotherplugin',
 +
              'version' => '1.0.0',
 +
              'operator' => '>'),
 +
 +
        // Multiple dependencies are allowed for the same parent plugin
 +
        // The below line ensures that only 'someplugin' with version less than 2.0.0 is used
 +
        array('plugin' => 'someotherplugin',
 +
              'version' => '2.0.0',
 +
              'operator' => '<'),
 +
 +
        // You can also require a particular range of versions of geeklog
 +
        array('core' => 'geeklog',
 +
              'version' => '1.8.0'),
 +
 +
        // You must require either all or none of the databases that your plugin supports
 +
        // Or you might lock out some of the capabilities of your plugin
 +
        array('db' => 'mysql'),
 +
 +
        array('db' => 'mssql',
 +
              'version' => '9.0'), // At least SQL Server 2005
 +
 +
        array('db' => 'pgsql',
 +
              'version' => '7.3',
 +
              'operator' => '>')
 +
    );
 +
 +
    $inst_parms = array(
 +
        'info'      => $info,
 +
        'groups'    => $groups,
 +
        'features'  => $features,
 +
        'mappings'  => $mappings,
 +
        'tables'    => $tables,
 +
        'requires'  => $requires // Add the dependency information to the installation parameters here
 +
    );
 +
 +
...</pre>
  
 
'''Note:''' Expect this function to be called more than once during installation. Also, the fact that the function is being called at all does not necessarily mean that the plugin will actually be installed.
 
'''Note:''' Expect this function to be called more than once during installation. Also, the fact that the function is being called at all does not necessarily mean that the plugin will actually be installed.
 +
  
 
== plugin_postinstall_ ==
 
== plugin_postinstall_ ==
  
Geeklog, armed with the information provided by the <code>plugin_autoinstall_</code> function, will take care of moving the plugin's files into their 3 standard locations, create the tables, the groups, and permissions. For any additional steps that need to performed during installation, the <code>plugin_postinstall_</code> function will be called:
+
Geeklog, armed with the information provided by the <code>plugin_autoinstall_</code> function, will take care of moving the plugin's files into their 3 standard locations, create the tables, the groups, and permissions. For any additional steps that need to be performed during installation, the <code>plugin_postinstall_</code> function will be called:
  
 
<pre>function plugin_postinstall_foo($pi_name)</pre>
 
<pre>function plugin_postinstall_foo($pi_name)</pre>
  
 
At this point, all the files are already in their correct place, the groups and permissions have been added and the plugin has been registered with Geeklog (i.e. has been added to the <tt>gl_plugins</tt> table). However, the plugin has not been loaded yet, i.e. you can not rely on any of your plugin's functions being available.
 
At this point, all the files are already in their correct place, the groups and permissions have been added and the plugin has been registered with Geeklog (i.e. has been added to the <tt>gl_plugins</tt> table). However, the plugin has not been loaded yet, i.e. you can not rely on any of your plugin's functions being available.
 +
 +
 +
== plugin_compatible_with_this_version_ ==
 +
 +
The very first function from <tt>autoinstall.php</tt> that Geeklog attempts to call is <code>plugin_compatible_with_this_version_</code>. Here, the plugin can check if it's compatible with the current Geeklog version. Since this function was only introduced in Geeklog 1.6.0, you can assume this to be the minimum version.
 +
 +
<pre>function plugin_compatible_with_this_version_foo($pi_name)</pre>
 +
 +
The function should return <code>false</code> when the plugin requires a more recent Geeklog version. Return <code>true</code> if installation on the current Geeklog version is okay.
 +
 +
If you would like to rely on Geeklog's "Plugin dependencies and version control" feature for ensuring that all required plugin are available, you must ensure that the user has at least version 1.8.0 of Geeklog. This can be accomplished with the following code snippet:
 +
 +
<pre>function plugin_compatible_with_this_version_foo($pi_name) {
 +
  if (function_exists('PLG_resolveDependencies')) {
 +
      return true;
 +
  } else {
 +
      COM_errorLog('Plugin "foo" requires at least Geeklog 1.8.0, but you are running an older version.');
 +
      return false;
 +
  }
 +
}</pre>
 +
 +
 +
== plugin_load_configuration_ ==
 +
 +
This function only needs to be implemented by plugins that use the [[PluginConfiguration|Configuration GUI]]. A typical implementation would look like this:
 +
 +
<pre>function plugin_load_configuration_foo($pi_name)
 +
{
 +
    global $_CONF;
 +
 +
    $base_path = $_CONF['path'] . 'plugins/' . $pi_name . '/';
 +
 +
    require_once $_CONF['path_system'] . 'classes/config.class.php';
 +
    require_once $base_path . 'install_defaults.php';
 +
 +
    return plugin_initconfig_foo();
 +
}</pre>
 +
 +
Where the <code>plugin_initconfig_foo</code> function is implemented in a <tt>install_defaults.php</tt> file, that handles creation and updates of the plugin's config GUI elements.
 +
 +
 +
= Also see =
 +
 +
* [[Plugin Auto-Uninstall]]
 +
 +
 +
[[Category:Plugin Development]]

Latest revision as of 14:58, 2 May 2011

Introduction

Geeklog 1.6 brings two important changes regarding installation of plugins:

  • Plugins can be installed by uploading their tarball (from Geeklog's Plugins Admin panel)
  • Plugins can be bundled / unbundled by simply adding / removing their respective directories to / from the Geeklog tarball

In both of these scenarios, Geeklog needs a way to automatically run the install procedure for such a plugin.

The problem with the plugin install scripts used until now are that they were mainly aimed at being run by a human and that they also check permissions that simply may not be set when the install is done (e.g. when running Geeklog's install script).

The solution proposed here is the inclusion of a new file, autoinstall.php into every plugin that implements up to 4 new API functions (3 of which are optional).

autoinstall.php

The file autoinstall.php is to be located in the plugin's main directory, i.e. in the same directory as its functions.inc file:

/path/to/geeklog/plugins/
                         foo/
                             functions.inc
                             autoinstall.php
                         staticpages/
                             functions.inc
                             autoinstall.php
                         ...

Plugins that ship with an autoinstall.php file won't need to provide the "traditional" install script (admin/plugins/foo/install.php) unless they want to be backward-compatible with Geeklog releases prior to 1.6.


plugin_autoinstall_

This is the most important and mandatory API function to implement in autoinstall.php:

function plugin_autoinstall_foo($pi_name)
{
    $pi_name         = 'foo';
    $pi_display_name = 'Foo';
    $pi_admin        = $pi_display_name . ' Admin';

    $info = array(
        'pi_name'         => $pi_name,
        'pi_display_name' => $pi_display_name,
        'pi_version'      => '1.0.0',
        'pi_gl_version'   => '1.6.0',
        'pi_homepage'     => 'http://www.example.com/'
    );

    $groups = array(
        $pi_admin => 'Has full access to ' . $pi_display_name . ' features'
    );

    $features = array(
        $pi_name . '.edit'      => 'Access to ' . $pi_display_name . ' editor'
    );

    $mappings = array(
        $pi_name . '.edit'      => array($pi_admin)
    );

    $tables = array(
        'foo'
    );

    $inst_parms = array(
        'info'      => $info,
        'groups'    => $groups,
        'features'  => $features,
        'mappings'  => $mappings,
        'tables'    => $tables
    );

    return $inst_parms;
}

If you've written a Geeklog plugin before, the data provided by this function should look familiar.

The $info array provides the information that goes into the plugin's entry in the gl_plugins table. The only addition here is the $pi_display_name entry, so that we can use a nicely formatted name to present to the user instead of having to refer to the plugin by its internal and possibly abbreviated name ($pi_name).

$groups and $features simply list all the groups and features (permissions) that the plugin would like to introduce. Geeklog will create those automatically for the plugin, using the $mappings. $mappings defines which permissions to assign to which of the new groups.

The $tables array obviously lists all the table names used by the plugin (note that the names are given without the $_DB_table_prefix). Geeklog will add these tables names (with the proper prefix) to the global $_TABLES array during the install. The plugin will still have to make sure they are known after the install, e.g. by defining them in its functions.inc file.

Finally, all these arrays are wrapped into another array and returned from the autoinstall function.

With the exception of the $info array, all of these arrays are optional. Plugins that don't create any groups or tables don't need to provide $groups or $tables entries.

In case of an error during the install, Geeklog will also use this information to attempt a cleanup of the database, i.e. remove groups, permissions, etc.

Plugin dependencies and version control

Since Geeklog 1.8.0, a new and optional array, $requires, is available. It must contain dependency information for a plugin. You can make a requirement for a particular range of versions of Geeklog, databases and other plugins. Each dependency is stored inside this array as another array.

The minimal usage is as follows:

...
    $requires= array(
        // This plugin requires another plugin, 'someplugin', and does not need a databases to function.
        array('plugin' => 'someplugin')
    );
...
...
    $requires= array(
        // This plugin requires another plugin, 'someplugin', and supports MySQL and PgSQL databases.
        array('plugin' => 'someplugin'),
        array('db' => 'mysql'),
        array('db' => 'pgsql')
    );
...

You can define any particular range of versions as the requirements for your plugin by adding the 'version' and 'operator' indeces to the arrays. Here's a more complex example:

...

    $requires= array(
        // This plugin requires a version greater than or equal to 1.0.0 of 'someplugin' (The default 'operator' is '>=')
        array('plugin' => 'someplugin',
              'version' => '1.0.0'),

        // This plugin also requires a version greater than 1.0.0 of 'someotherplugin'
        array('plugin' => 'someotherplugin',
              'version' => '1.0.0',
              'operator' => '>'),

        // Multiple dependencies are allowed for the same parent plugin
        // The below line ensures that only 'someplugin' with version less than 2.0.0 is used
        array('plugin' => 'someotherplugin',
              'version' => '2.0.0',
              'operator' => '<'),

        // You can also require a particular range of versions of geeklog
        array('core' => 'geeklog',
              'version' => '1.8.0'),

        // You must require either all or none of the databases that your plugin supports
        // Or you might lock out some of the capabilities of your plugin
        array('db' => 'mysql'),

        array('db' => 'mssql',
              'version' => '9.0'), // At least SQL Server 2005

        array('db' => 'pgsql',
              'version' => '7.3',
              'operator' => '>')
    );

    $inst_parms = array(
        'info'      => $info,
        'groups'    => $groups,
        'features'  => $features,
        'mappings'  => $mappings,
        'tables'    => $tables,
        'requires'  => $requires // Add the dependency information to the installation parameters here
    );

...

Note: Expect this function to be called more than once during installation. Also, the fact that the function is being called at all does not necessarily mean that the plugin will actually be installed.


plugin_postinstall_

Geeklog, armed with the information provided by the plugin_autoinstall_ function, will take care of moving the plugin's files into their 3 standard locations, create the tables, the groups, and permissions. For any additional steps that need to be performed during installation, the plugin_postinstall_ function will be called:

function plugin_postinstall_foo($pi_name)

At this point, all the files are already in their correct place, the groups and permissions have been added and the plugin has been registered with Geeklog (i.e. has been added to the gl_plugins table). However, the plugin has not been loaded yet, i.e. you can not rely on any of your plugin's functions being available.


plugin_compatible_with_this_version_

The very first function from autoinstall.php that Geeklog attempts to call is plugin_compatible_with_this_version_. Here, the plugin can check if it's compatible with the current Geeklog version. Since this function was only introduced in Geeklog 1.6.0, you can assume this to be the minimum version.

function plugin_compatible_with_this_version_foo($pi_name)

The function should return false when the plugin requires a more recent Geeklog version. Return true if installation on the current Geeklog version is okay.

If you would like to rely on Geeklog's "Plugin dependencies and version control" feature for ensuring that all required plugin are available, you must ensure that the user has at least version 1.8.0 of Geeklog. This can be accomplished with the following code snippet:

function plugin_compatible_with_this_version_foo($pi_name) {
   if (function_exists('PLG_resolveDependencies')) {
       return true;
   } else {
       COM_errorLog('Plugin "foo" requires at least Geeklog 1.8.0, but you are running an older version.');
       return false;
   }
}


plugin_load_configuration_

This function only needs to be implemented by plugins that use the Configuration GUI. A typical implementation would look like this:

function plugin_load_configuration_foo($pi_name)
{
    global $_CONF;

    $base_path = $_CONF['path'] . 'plugins/' . $pi_name . '/';

    require_once $_CONF['path_system'] . 'classes/config.class.php';
    require_once $base_path . 'install_defaults.php';

    return plugin_initconfig_foo();
}

Where the plugin_initconfig_foo function is implemented in a install_defaults.php file, that handles creation and updates of the plugin's config GUI elements.


Also see