This document is replaced by DevelopingPlugins

How to integrate extension configuration into bin/configure

Introduction

Simple plugins can embed configuration data in the 'Plugin' topic added to the System web when the plugin is installed. This technique is maintained for compatibility with TWiki, but it is very inefficient and is discouraged in Foswiki.

Instead, the Foswiki configure interface supports enhanced configuration for extensions (i.e. beyond simple "Enabled" for plugins). The benefits are:
  • Performance is much better because plugin topics don't have to be parsed for every request
  • No need for site admins to modify files from the installed package (which should always be read-only)
  • Complex Perl data structures can be initialized
  • Single administration interface bin/configure for both core and extension settings
  • Increased security for sensitive configuration data and account information

This topic describes how an extension author can make their settings be picked up by configure.

Overview

Here is the high-level overview:
  1. Create a Config.spec file in the extension directory
    • In SVN trunk, this is XXX/lib/Foswiki/Plugins/XXX/Config.spec for a plugin named XXX, YYY/lib/Foswiki/Contrib/YYY/Config.spec for a contrib (or Skin, or anything else) named YYY.
    • in a live installation, this is the lib/Foswiki/Plugins/XXX/ directory for a plugin named XXX
  2. In that spec file, add your configuration requirements by following the style of the examples below.
  3. When configure is run the configuration options will be available through the interface. The default settings read will be saved along with the rest of the configuration.

Examples:
# ---+ Extensions
# ---++ JSCalendarContrib
# **STRING 30**
# Calendar style. The following styles are shipped by default with the
# Mishoo DHTML calendar: # blue, blue2, brown, green, setup, system, tas, win2k-1, win2k-2,
# win2k-cold-1, win2k-cold-2. Your local site may have other locally-defined styles.
$Foswiki::cfg{JSCalendarContrib}{style} = 'blue';
# **STRING 5**
# Controls what language is used in calendars.
$Foswiki::cfg{JSCalendarContrib}{lang} = 'en';
1;
In the above example, the configuration for JSCalendarContrib is being added as a subsection of the Extensions section. There are two configuration items, indicated by the type declarations **STRING 30** and **STRING 5**. Each type declaration is followed by a comment (which is displayed in configure) and the actual declaration $Foswiki::cfg{...} = ...;. STRING 30 tells configure that the value expected is a string, and it should display a 30 character wide prompt box.

From Plugins.Foswiki::Plugins::Plugins.EditTablerowPlugin
# ---+ Extensions
# ---++ EditTablerowPlugin
# **BOOLEAN**
# Debug setting
$Foswiki::cfg{Plugins}{EditTablerowPlugin}{DEBUG} = $FALSE;
1;
Here a different type, BOOLEAN, is being used. For a full list of the available types, see below.

A note on performance: If you are writing a plugin, and all your configuration settings are in your .spec file, then remember to set our $NO_PREFS_IN_TOPIC=1 in your plugin (as described in lib/Foswiki/Plugins/EmptyPlugin.pm). This will tell Foswiki that it doesn't have to parse the plugin topic for settings every time it runs.

The details of .spec files

.spec files are executable perl files that are read by configure using the perl do function. Their purpose is twofold:
  1. to allow an extension author to include new fields in the $Foswiki::cfg configuration hash that can then be referred to by the extension.
  2. to support setting those values from the configure interface.
configure reads .spec files twice; once using do to extract the default values for each field, and then again to extract formatted comments that tell configure how to present the field in the configure UI.

.spec files are only read by configure. When Foswiki runs, it reads LocalSite.cfg (generated by configure) but not .spec files. So any changes you make to a .spec file will not be seen in Foswiki until after you run configure and save.

Structure of a .spec file

A .spec file is structured using Foswiki-syntax headings. ---+ defines a top level section, while ---++ will create a running subsection within that section.

All extensions (Plugins, Skins, Applications, Contribs etc) should use the ---+ Extensions section. You can place configuration into other sections, but keeping everything inside Extensions makes the configure interface cleaner for the end user. All extensions should define their own sub-section. For example,
# ---+ Extensions
# ---++ MyContrib
# This extension supports firtling, graunching, munging and general dibbling.
After the heading comes a header comment for the section, and then a list of one or more fields. Each field is introduced by a type comment which describes how the field is to be presented in configure. For example,
# **STRING 30 EXPERT**
# Options for the <tt>graunch</tt> command
introduces a field which is expected to take a string value and will be prompted for using a 30-character wide text field. The field type name may be followed by one or more attributes which further refine the type - in the example above, 30 is an attribute that declares the width of the text field, and EXPERT indicates that the setting is only for experts. More detail on types and their attributes can be found below.

The type declaration is followed by a descriptive comment (which can be formatted using raw HTML, not Foswiki syntax).
# **SELECT blue rinse,mullet,beehive**
# Style setting. This sets the required <strong>hair style</strong>.
After this comment comes the default value for the field. This value will be overridden by the value read from LocalSite.cfg when configure is run. It exists just to make that all fields have a value.
$Foswiki::cfg{MyContrib}{style} = 'blue rinse';
ALERT! When an extension is first installed, Foswiki will not pick up these defaults until after configure has been run and the configuration saved. To prevent your extension from falling over when run this way, you should always provide intelligent defaults for configuration items in the code.

Putting it all together, we get the .spec for MyContrib:
#---+ Extensions
#---++ MyContrib
# This extension supports graunching, munging and general dibbling.
# **STRING 30 EXPERT**
# Options for the <tt>graunch</tt> command
$Foswiki::cfg{MyContrib}{graunch} = "--flibble --nomunge";
# **SELECT blue rinse,mullet,beehive**
# Style setting. This sets the required <bold>hair style</bold>.
$Foswiki::cfg{MyContrib}{style} = 'blue rinse';

Namespaces

Keep your configuration values in the appropriate namespace. Plugins each have their own configuration namespace, viz. $Plugins.Foswiki::Cfg{Plugins}{XXX} where XXX is the name of the plugin. All Enabled flags and {Module} settings are already in this namespace e.g. $Plugins.Foswiki::cfg{Plugins}{ActionTrackerPlugin}{Enabled} = 1;

Contribs, Skins, AddOns and Applications should all occupy the Extensions namespace e.g. $Plugins.Foswiki::cfg{Extensions}{MailInContrib}{DEBUG} = 0;.

The namespaces for Plugins and Extensions are deliberately kept separate because Plugins can be selectively enabled and disabled, whereas other types of extension are always enabled if they are installed.

Types

The following field types are supported in .spec files:
Type name Description Attributes Example
BOOLEAN Boolean value - **BOOLEAN**
COMMAND String representing an operating system command - **COMMAND**
LANGUAGE
NUMBER Numerical value - **NUMBER**
OCTAL Octal (permissions) value - **OCTAL**
PASSWORD Password (hidden) - **PASSWORD**
PATH File path - **PATH**
PERL Arbitrary perl value - **PERL**
REGEX Regular expression - **COMMAND**
SELECT Choices Comma-separated list of legal values **SELECT crypt,sha1,md5,plain**
SELECTCLASS Choice of classes/packages, where package names may be matched from disc. List of package names. Package specifications may include wildcards; in the example, all package with names ending in Login will be selected from the Foswiki::Client package. none is a special name used to indicate no choice. **SELECTCLASS none,Plugins.Foswiki::Client::*Login**
STRING Arbitrary text string width **STRING 30**
URL Absolute URL - **URL**
URLPATH Relative URL - **URLPATH**

All fields support some common attributes:
EXPERT Indicates that this is an expert setting. This just generates a slightly different UI.
M Indicates this setting is mandatory (must have a value for Foswiki to run)
H If this is present, the field will not be shown in configure

Note that these types are supported because there is a .pm file for the type in the lib/Foswiki/Configure/Types directory. Extensions may add other types by installing an appropriate .pm to this directory. The .pm may define the following functions:
prompt Generates the HTML to prompt for a value
string2value Used to convert from the string returned by $query->param() to the actual stored value
equals Used to compare two values of this type
onUpdate Invoked if a value of this type is changed
See the code for examples and function specs.

A note on the PERL type

The PERL type allows you to enter simple perl data structures for values. The value entered by a user must be valid perl, but that is the limit of the checking. If you use the PERL type, you are strongly recommended to implement a Checker for the field (see Checkers, below).

PERL H Switchboard entries

If your extension will be implementing a new CGI script, you also have to populate a Switchboard entry. This can be entered as a "Hidden PERL" type spec. Note that the user must visit and save in /bin/configure to apply the hidden attribute even though it may appear that nothing has changed. See Development/FoswikiStandAlone#Note_to_Extension_Developers for more details.
# **PERL H**
# This setting is required to enable executing "myscript" script from the bin directory
$Foswiki::cfg{SwitchBoard}{myscript} = {
    package  => 'Foswiki::Contrib::MyContrib',
    function => 'myFunction',
    context  => { view => 1 },
    };

Checkers

configure supports optional checkers for values. These checkers are short pieces of perl code that validate the values entered by the configure user and generate informational messages. Checkers are packages in lib/Foswiki/Configure/Checkers that are named for the field they check. Checker packages define a single function, check. This function is used to perform value validation. For example, we might have a .spec as follows:
#---+ Extensions
#---++ MyContrib
# The contrib is responsible for firtling, graunching, munging and general dibbling.
# **SELECT blue rinse,mullet,beehive**
# Style setting. This sets the <i>required</i> hair style.
$Foswiki::cfg{MyContrib}{style} = 'blue rinse';
A checker for this item would be installed in lib/Foswiki/Configure/Checkers/MyContrib/style.pm, and would contain:
package Foswiki::Configure::Checkers::MyContrib::style;
use base 'Foswiki::Configure::Checkers::Checker';

sub check {
    my $this = shift; # This object is used to generate warning and error strings

    if ($Foswiki::cfg{MyContrib}{style} eq 'mullet') {
        return $this->WARNING("Mullets went out of fashion in the 1980's");
    } elsif ($Foswiki::cfg{MyContrib}{style} eq 'blue rinse') {
        return $this->ERROR("Blue rinses are reserved for little old ladies");
    }
    return '';
}
The string returned by check will be used to generate a warning/error message in configure. Checkers can also be used to 'guess' values based on platform inspection. See lib/Foswiki/Configure/Checkers/DataDir.pm for an example of this approach.

There are many checkers pre-installed in Foswiki to check the standard configuration items. You can read the code of these checkers to gain inspiration for your own.

Specialised User Interfaces (UIs)

configure supports the inclusion of specialised UIs for very complex applications. For example, the extensions installer is a specialised UI, as is the Plugin enabler. Specialised UIs are packages stored in the lib/Foswiki/Configure/UIs directory. You have to be very expert to use them, and there is almost no documentation. Contact CrawfordCurrie if you need help with this.

Related topics: System.Plugins, ExtensionDeveloperGuide

Topic revision: r8 - 13 May 2013, MichaelDaum
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy