glFusion Wiki

Site Tools


glfusion:development:pluginautoinstall

glFusion Automated Plugin Installation

(glFusion v1.1.2)

glFusion now supports the ability to upload and automatically install or upgrade a plugin. For the end user, the process is very simple, they choose the plugin to upload and the rest is done automatically.

There are several checks performed to ensure the plugin is compatible with the glFusion environment. Some of the checks performed are:

  • Validate the plugin is not already installed
  • Validate the plugin is newer than a previously installed version
  • Validate the plugin meets the proper glFusion and PHP version requirements
  • Validate any prerequisite plugins are already installed
  • Validate file and directory permissions to ensure the plugin files can be copied successfully

There is also support for older style plugins, those that have not been updated to include the 2 new auto install files. For older plugins, the files will be copied to the correct location, but the user must still select install or upgrade from the Plugin Administration screen.

Required Auto Installer Files

plugin.xml

To facilitate plugin installation, and to assist in validating the environment, each plugin must contain a simple XML file called plugin.xml in it's root directory. This file specifies the minimum requirements needed for the plugin. The plugin.xml file also contains special instructions for the installer to assist with installing configuration files, ensuring that existing files are not overwritten.

<plugin>
    <id>calendar</id>
    <name>Calendar</name>
    <description>Online Calendar System</description>
    <version>1.0.3.fusion</version>
    <glfusionversion>1.1.2</glfusionversion>
    <phpversion>4.3.0</phpversion>
    <url>http://www.glfusion.org</url>
    <maintainer>Mark R. Evans</maintainer>
</plugin>

As you can see, this is a very simple file with the following attributes defined:

Attribute Description
id The plugin ID (used for directory creation and the value stored in the pi_name column)
name The name of the plugin (used for presentation)
description A description of the plugin (optional)
version The version of this plugin
glfusionversion The minimum version of glFusion required to support this plugin
phpversion The minimum version of PHP to support this plugin
url URL to the location of the plugin's support
maintainer The name of the plugin maintainer (optional)
requires The name of any plugin that must be installed before this plugin. This attribute can appear multiple times if there are multiple prerequisites. (optional)
dataproxydriver Defines the source file name of a dataproxy plugin driver. The driver must exist in the dataproxy sub-directory in the plugin archive. (Optional)
layout Defines the name of the directory to create and place all the themefiles into. This directory will be created directly under the layout/ directory. (Optional)
renamedist If there is a configuration file that needs to be renamed, provide the path and the .dist name (optional)

The layout parameter would be used by a plugin like Chameleon, where it needs to have theme files placed directly under the layout/ directory.

If a plugin has a themefiles directory, but does not define the layout attribute, the theme files will be copied to layout/nouveau/pluginname/ directory.

The renamedist parameter would be used by a plugin to install it's own config.php file. For example, if your plugin has a config.php file to allow site administrators to customize the plugin's functions, you would include a config.php.dist file in your distribution archive. On a new installation, the installer would automatically copy the config.php.dist file to config.php, but on an upgrade, it would not overwrite the existing config.php.

If the config.php resides in the plugins root directory, the following entry would be used:

<renamedist>config.php.dist</renamedist>

If the config.php file resides in the plugin's public_html/ directory, the following entry would be used:

<renamedist>public_html/config.php.dist</renamedist>

autoinstall.php

The autoinstall.php file will be called to install the plugin after the files are loaded. The autoinstaller will use lib-install.php to perform the actual installation.

The autoinstall.php must define the following required items:

  • $INSTALL_plugin['pluginname'] array
    • plugin_install_pluginname() function
    • plugin_autouninstall_pluginname() function

Optional functions that can be included in autoinstall.php:

  • plugin_load_configuration_pluginname() - Used if the plugin will use the online configuration
  • plugin_postinstall_pluginname() - Any post install operations that must be peformed

A sample autoinstall.php is shown below.

if (!defined ('GVERSION')) {
    die ('This file can not be used on its own.');
}
 
global $_DB_dbms;
 
require_once $_CONF['path'].'plugins/calendar/functions.inc';
require_once $_CONF['path'].'plugins/calendar/calendar.php';
require_once $_CONF['path'].'plugins/calendar/sql/'.$_DB_dbms.'_install.php';
 
// +--------------------------------------------------------------------------+
// | Plugin installation options                                              |
// +--------------------------------------------------------------------------+
 
$INSTALL_plugin['calendar'] = array(
  'installer' => array('type' => 'installer', 'version' => '1', 'mode' => 'install'),
 
  'plugin' => array('type' => 'plugin',   'name'    => $_CA_CONF['pi_name'],
        'ver' => $_CA_CONF['pi_version'], 'gl_ver'  => $_CA_CONF['gl_version'],
        'url' => $_CA_CONF['pi_url'],     'display' => $_CA_CONF['pi_display_name']),
 
  array('type' => 'table', 'table' => $_TABLES['events'], 'sql' => $_SQL['events']),
  array('type' => 'table', 'table' => $_TABLES['eventsubmission'], 'sql' => $_SQL['eventsubmission']),
  array('type' => 'table', 'table' => $_TABLES['personal_events'], 'sql' => $_SQL['personal_events']),
 
  array('type' => 'group', 'group' => 'calendar Admin', 'desc' => 'Users in this group can administer the Calendar plugin',
        'variable' => 'admin_group_id', 'addroot' => true),
 
  array('type' => 'feature', 'feature' => 'calendar.edit', 'desc' => 'Ability to edit Calendar events',
        'variable' => 'edit_feature_id'),
  array('type' => 'feature', 'feature' => 'calendar.moderate', 'desc' => 'Ability to moderate Calendar events',
        'variable' => 'moderate_feature_id'),
  array('type' => 'feature', 'feature' => 'calendar.submit', 'desc' => 'Ability to submit Calendar events',
        'variable' => 'submit_feature_id'),
 
  array('type' => 'mapping', 'group' => 'admin_group_id', 'feature' => 'edit_feature_id',
        'log' => 'Adding feature to the admin group'),
  array('type' => 'mapping', 'group' => 'admin_group_id', 'feature' => 'moderate_feature_id',
        'log' => 'Adding feature to the admin group'),
  array('type' => 'mapping', 'group' => 'admin_group_id', 'feature' => 'submit_feature_id',
        'log' => 'Adding feature to the admin group'),
 
  array('type' => 'block',  'name' => 'block_calevents', 'title' => 'Upcoming Events',
          'phpblockfn' => 'phpblock_calendar', 'block_type' => 'phpblock',
          'group_id' => 'admin_group_id'),
 
);
/**
* Puts the datastructures for this plugin into the glFusion database
*
* Note: Corresponding uninstall routine is in functions.inc
*
* @return   boolean True if successful False otherwise
*
*/
function plugin_install_calendar()
{
    global $INSTALL_plugin, $_CA_CONF;
 
    $pi_name            = $_CA_CONF['pi_name'];
    $pi_display_name    = $_CA_CONF['pi_display_name'];
    $pi_version         = $_CA_CONF['pi_version'];
 
    COM_errorLog("Attempting to install the $pi_display_name plugin", 1);
 
    $ret = INSTALLER_install($INSTALL_plugin[$pi_name]);
    if ($ret > 0) {
        return false;
    }
 
    return true;
}
 
 
/**
* Loads the configuration records for the Online Config Manager
*
* @return   boolean     true = proceed with install, false = an error occured
*
*/
function plugin_load_configuration_calendar()
{
    global $_CONF;
 
    require_once $_CONF['path'].'plugins/calendar/install_defaults.php';
 
    return plugin_initconfig_calendar();
}
 
 
/**
* When the install went through, give the plugin a chance for any
* plugin-specific post-install fixes
*
* @return   boolean     true = proceed with install, false = an error occured
*
*/
function plugin_postinstall_calendar()
{
    global $_CONF, $_TABLES, $LANG_CAL_1;
 
    require_once $_CONF['path'].'plugins/calendar/functions.inc';
 
    // fix Upcoming Events block group ownership
    $blockAdminGroup = DB_getItem ($_TABLES['groups'], 'grp_id',
                                   "grp_name = 'Block Admin'");
    if ($blockAdminGroup > 0) {
        // set the block's permissions
        $A = array ();
        SEC_setDefaultPermissions ($A, $_CONF['default_permissions_block']);
 
        // set the block's title in the current language, while we're at it
        $title = 'Upcoming Events';
 
        // ... and make it the last block on the left side
        $result = DB_query ("SELECT MAX(blockorder) FROM {$_TABLES['blocks']} WHERE onleft = 1");
        list($order) = DB_fetchArray ($result);
        $order += 10;
 
        DB_query ("UPDATE {$_TABLES['blocks']} SET group_id = $blockAdminGroup, title = '$title', blockorder = $order, perm_owner = {$A['perm_owner']}, perm_group = {$A['perm_group']}, perm_members = {$A['perm_members']}, perm_anon = {$A['perm_anon']} WHERE (type = 'phpblock') AND (phpblockfn = 'phpblock_calendar')");
 
        return true;
    }
 
    return false;
}
 
/**
* Automatic uninstall function for plugins
*
* @return   array
*
* This code is automatically uninstalling the plugin.
* It passes an array to the core code function that removes
* tables, groups, features and php blocks from the tables.
* Additionally, this code can perform special actions that cannot be
* foreseen by the core code (interactions with other plugins for example)
*
*/
function plugin_autouninstall_calendar ()
{
    $out = array (
        /* give the name of the tables, without $_TABLES[] */
        'tables' => array('events','eventsubmission','personal_events'),
        /* give the full name of the group, as in the db */
        'groups' => array('calendar Admin'),
        /* give the full name of the feature, as in the db */
        'features' => array('calendar.edit', 'calendar.moderate', 'calendar.submit'),
        /* give the full name of the block, including 'phpblock_', etc */
        'php_blocks' => array('phpblock_calendar'),
        /* give all vars with their name */
        'vars'=> array()
    );
    return $out;
}

pluginname.php

The actual filename is the name of the plugin. For example, the Calendar plugin is named calendar.php, the evList plugin is named evlist.php.

This is where you should define the pi_ variables.

if (!defined ('GVERSION')) {
    die ('This file can not be used on its own.');
}

global $_DB_table_prefix, $_TABLES;

// Plugin info

$_CA_CONF['pi_name']            = 'calendar';
$_CA_CONF['pi_display_name']    = 'Calendar';
$_CA_CONF['pi_version']         = '1.0.3';
$_CA_CONF['gl_version']         = '1.1.2';
$_CA_CONF['pi_url']             = 'http://www.glfusion.org/';

// Define database tables

$_TABLES['events']              = $_DB_table_prefix . 'events';
$_TABLES['eventsubmission']     = $_DB_table_prefix . 'eventsubmission';
$_TABLES['personal_events']     = $_DB_table_prefix . 'personal_events';

install.php

require_once '../../../lib-common.php';
require_once $_CONF['path'].'/plugins/calendar/autoinstall.php';

USES_lib_install();

if (!SEC_inGroup('Root')) {
    // Someone is trying to illegally access this page
    COM_errorLog("Someone has tried to illegally access the Calendar install/uninstall page.  User id: {$_USER['uid']}, Username: {$_USER['username']}, IP: $REMOTE_ADDR",1);
    $display = COM_siteHeader ('menu', $LANG_ACCESS['accessdenied'])
             . COM_startBlock ($LANG_ACCESS['accessdenied'])
             . $LANG_ACCESS['plugin_access_denied_msg']
             . COM_endBlock ()
             . COM_siteFooter ();
    echo $display;
    exit;
}

/**
* Main Function
*/

if (SEC_checkToken()) {
    $action = COM_applyFilter($_GET['action']);
    if ($action == 'install') {
        if (plugin_install_calendar()) {
    		// Redirects to the plugin editor
    		echo COM_refresh($_CONF['site_admin_url'] . '/plugins.php?msg=44');
    		exit;
        } else {
    		echo COM_refresh($_CONF['site_admin_url'] . '/plugins.php?msg=72');
    		exit;
        }
    } else if ($action == 'uninstall') {
    	if (plugin_uninstall_calendar('installed')) {
    		/**
    		* Redirects to the plugin editor
    		*/
    		echo COM_refresh($_CONF['site_admin_url'] . '/plugins.php?msg=45');
    		exit;
    	} else {
    		echo COM_refresh($_CONF['site_admin_url'] . '/plugins.php?msg=73');
    		exit;
    	}
    }
}

echo COM_refresh($_CONF['site_admin_url'] . '/plugins.php');
?>

The autoinstall.php uses the lib-install.php library to make the installation painless for the developer.

Pitfalls to Avoid

Keep in mind that the install_defaults.php file is included from the autoinstall.php, which is included from plugin_upload.php. What this means is that anything you have defined in your plugin's functions.inc won't be available.

The plugin's config.php file is included, but you also have to be very careful about global variables, make sure you define them in all the right places.

glfusion/development/pluginautoinstall.txt · Last modified: 2017/04/12 21:11 (external edit)

Page Tools