user-pic

HOWTO: Define custom plugin settings

Vote 0 Votes

Working on an addition to the Movable Type developer guide which I wanted to post here first for feedback:

Plugin Settings

Often plugins need a way to allow their users to customize and configure their behavior in some way. For example, an Amazon plugin may want collect your Amazon Associates ID to embed within a link it generates. Or perhaps a theme or template set wants to make it easy for users to change the color scheme, or header image. Regardless of what options you need to surface to your users, Movable Type offers a relatively simple system for doing so.

This system works by editing your plugin's config.yaml and registering a set of plugin settings, and the templates that will be used for rendering the user interface and form for editing those settings.

The following guide will take you through this process, and then show you some alternatives that make this process even easier.

Registering Plugin Settings

Step one is registering each of the individual settings you will need to make available to your users. In this first step we are not defining the UI for these settings, just that the settings exist, their default values, their scope and what names will be used for storing and retrieving the values they hold.

Here is a small excerpt from a plugin that defines a single setting with a look up key of my_setting:

Sample config.yaml

name: Example Plugin for Movable Type
id: Example
description: This plugin is an example plugin for Movable Type.
settings:
  my_setting:
    default: "Byrne"
    scope: blog

Registry Properties

  • default - the default value for this plugin setting when no value has been explicitly provided by the user.

  • scope - the scope for which this setting applies. A value of "system" will indicate to Movable Type to store only one value for this setting across the entire installation, whereas a value of "blog" will instruct Movable Type to store a value for this setting for each blog in the system.

Registering a Plugin Settings Template

Once you have declared what settings will be collected, the next thing you need to do is create the UI for editing them. First you will need to register the config template that will be used for the system level or blog level (or both) settings interfaces. There are two registry properties you can use:

  • system_config_template
  • blog_config_template

Each of these properties takes a single value as input, the name of the template file used to render your settings. The template file you will create will need to be placed in your plugins tmpl directory.

Here is a sample config.yaml that shows these registry properties in action:


name: Example Plugin for Movable Type
id: Example
description: This plugin is an example plugin for Movable Type.
system\_config\_template: system_config.tmpl
blog_config_template: blog_config.tmpl
settings:
  my\_setting:
    default: "Byrne"
    scope: blog

Implementing a Settings Template

With your settings template or templates registered, time to actually implement one. Let's begin by creating a template called blog_config.tmpl and placing it in your plugins tmpl directory.

The first template we will create will expose a single text field with the label "My Setting." Here is the template code you would use:

<mtapp:setting
  id="my_setting"
  label="My Setting"
  hint="Enter any value you want here."
  show_hint="1">
    <input type="text" name="my_setting" id="my_setting" 
       value="<mt:var name="my_setting">" />
</mtapp:setting>

A couple things to note:

  1. The template above only defines the input elements themselves, the <form> tag that wraps your input element will be generated for you automatically by Movable Type.

  2. Movable Type automatically populates your template with variables that hold the current value of each of your plugin configuration settings. You can use any normal Movable Type template to access these values.

Finally, the single most important detail in making all of this work is utilizing a name for your form elements that are synchronized with the setting you defined for them in your config.yaml. Let's look at one more example. First your config.yaml:


settings:
  my\_favorite\_color:
    default: "Blue"
    scope: blog

And now the form element that will allow a user to provide a value for this setting:


<mtapp:setting
   id="my_setting"
   label="My Setting"
   hint="Enter any value you want here."
   show_hint="1">
<select name="my\_favorite\_color">
  <option>Red</option>
  <option>Yellow</option>
  <option>Green</option>
  <option>Blue</option>
</select>
</mtapp:setting>
You can include as many form elements that you want. To help you with the styling of these form elements, Movable Type provides the helper `` tag which makes creating the HTML markup for your forms much, much simpler. Let's take a closer look at the this template tag so that you can use its fullest benefit. **`` Properties** 7b827900ab2b886329042f835387c07e

Fetching Plugin Data

By now you should have successfully created a plugin that exposes a simple user interface that makes it possible for you to collect from your users configuration data for your plugin and for that information to be faithfully stored by Movable Type. The following section will instruct you on how to access that information once it has been stored. **Fetching a System-Level Setting** If you need to retrieve the value stored for a setting that is consider a system wide setting, then the following code should do the trick:
my $plugin = MT->component("MyPlugin");
my $my_setting = $plugin->get_config_hash('my_setting','system');

Fetching a Blog-Level Setting

Retrieving a blog-specific setting is very similar, and requires only one additional piece of information: the ID of the blog for which this setting applies:

my $plugin = MT->component("MyPlugin");
my $scope = "blog:" . $blog_id;
my $my_setting = $plugin->get_config_value('my_setting',$scope);

And finally, you can fetch all of the values associated with your plugin's preferences at once by using the get_config_hash method like so:

my $plugin = MT->component("MyPlugin");
my $scope = "blog:" . $blog_id;
my $config = $plugin->get_config_hash($scope);
my $my_setting = $config->{'my_setting'};

Using Configuration Assistant

Even with Movable Type's capable API for letting developers define their own custom user interfaces for collecting plugin preferences from their user's, there exists a far easier method by way of a plugin prototype called "Config Assistant." Config Assistant is useful because it reduces all of the work associated with collecting and accessing plugin configuration data to editing a config file.

To illustrate let's take a second look at the example explained in gory detail previously that surfaced a single text field called "My Setting." To accomplish that task you needed to:

  1. Register the setting in your config.yaml.
  2. Register a template for rendering your settings form.
  3. Create a template to display your setting form elements.

That entire process can be reduced to the following config.yaml file:

name: Example Plugin for Movable Type
id: Example
description: This plugin is an example plugin for Movable Type.
settings:
  my_setting:
    default: Byrne
    scope: blog
blog_config_template: '<mt:PluginConfigForm id="Example">'
plugin_config:
    Example:
        fieldset_1:
            my_setting:
                type: text
                label: "My Setting"
                hint: "Enter anything here."
                tag: 'MySetting'

After all that, this is what Config Assistant will output for your plugin's settings UI:

Config Assistant Example Screenshot

Config Assistant Registry Settings

Config Assistant is driven 100% by configuration data you place in your plugin's config.yaml. In addition to defining a new data structure for use within your config.yaml, Config Assistant makes use of the following registry keys as well:

  • settings - you still need to register the values that will be stored in the database.
  • blog_config_template and system_config_template - you also need to provide templates to properly display the form defined by the plugin_config registry data structure.

The new registry data structure parsed exclusively by Config Assistant is associated with the registry key plugin_config. This element has a single child element, corresponding to the plugin's id for which you are defining configuration options. It is this element which will contain each of your plugin's configuration options and input elements, grouped by fieldset. Let's look at an example that stubs out one possible plugin_config data structure:

plugin_config:
  MyPluginID:
    ServerInfo:
      server_host: *snip*
      server_port: *snip*
    PluginOptions: 
      use_https: *snip*
      http_auth_username: *snip*
      http_auth_password: *snip*

The sample above defines two field sets:

  • ServerInfo
  • PluginOptions

Each of these field sets will be encapsulated by the HTML element from which they get their name:

<fieldset id="ServerInfo">
  <!-- form elements go here -->
</fieldset>
<fieldset id="PluginOptions">
  <!-- form elements go here -->
</fieldset>

Field sets like this provide the benefit of visually grouping related configuration options together. They have no bearing on the functionality of your plugin.

Within each of these field sets, Config Assistant will render their associated form input elements, or "fields."

Each field then supports the following registry properties:

  • type - the type of the field. Supported values are: text, textarea, select, checkbox.

  • label - the label to display to the left of the input element

  • hint - the hint text to display below the input element

  • tag - the template tag that will access the value held by the corresponding input element

  • values - valid only for fields of type "select" - this contains a comma delimitted list of values to present in the pull down menu

  • rows - valid only for fields of type "textarea" - this corresponds to the number of rows of text displayed for the text area input element

Finally, in order for Config Assistant to properly surface the form under your plugin's settings area, you will need to define a blog configuration template using the blog_config_template registry property like so:

blog_config_template: '<mt:PluginConfigForm id="MyPluginID">'

Auto-Generated Template Tags

Each plugin configuration field can define a template tag by which a designer or developer can access its value. If a tag name terminates in a question mark then the system will interpret the tag as a block element. Here are two example configs:

feedburner_id:
    type: text
    label: "Feedburner ID"
    hint: "This is the name of your Feedburner feed."
    tag: 'FeedburnerID'
use_feedburner:
    type: checkbox
    label: "Use Feedburner?"
    tag: 'IfFeedburner?'

And here are corresponding template tags that make use of these configuration options:

<mt:IfFeedburner>
  My feedburner id is <mt:FeedburnerID>.
<mt:Else>
  Feedburner is disabled!
</mt:IfFeedburner>

6 Replies

| Add a Reply
  • user-pic

    I've just been having a go at this for a custom tag, and it is a great-looking procedure.

    It isn't clear, however, how you get the configuration settings from the context parameter in a tag subroutine. Could you add something for that?

    I've got my tag plugin up and running following this recipe: http://www.movabletype.org/documentation/developer/template-tag-handler.html. It gets its config from 'config_settings' in the config.yaml.

    Your procedure configures settings in 'settings' rather than 'config_settings'. It isn't obvious - without deeper knowledge - what to change to get both to work.

    Is there a way to reference 'settings' from the ctx parameter passed to the tag subroutine, or does it need to work with...


    my $plugin = MT->component("MyPlugin");
    # etc.

    ...instead?

  • Try $ctx->stash('blog_id') where $ctx is a MT::Template::Context object in your tag code to get the current blog id number.

  • user-pic

    Beware, there's a typo in this:

    my $my_setting = $plugin->get_config_hash('my_setting','system');

    Should be: get_config_value. [Use get_config_hash to get the hash.]

  • user-pic

    For what it's worth, I've got my tag working thus:

    sub tag {
            my ($ctx, $args) = @_;
            #my $cfg = $ctx->{config};
            my $plugin = MT->component("MyPlugin");
            my $cfg = $plugin->get_config_hash('system');
            my $system_setting = $cfg->{'my_system_setting'};
            my $scope = "blog:" . $ctx->stash('blog_id');
            $cfg = $plugin->get_config_hash($scope);
            my $blog_setting = $cfg->{'my_blog_setting'};
            return '';
    }
    

    It does however look a lot more bloated than simply using $ctx->{config}.

    I promise I'll stop bombarding you with comments now! :-)

  • As asked elsewhere, how do I access config variables in tmpl files for the plugin?

    Using tags breaks the page and using mt:var just outputs blank.

Add a Reply

If you need to share template code, replace all the "<" signs with "&lt;" or use this utility.

Forum Groups

1264 4145

Last Topic: HTML Table query by Parag on Mar 18, 2010

64 196

Last Topic: movable type 5 custom fields by kljx on Mar 17, 2010

1007 3224

Last Topic: http://www.tvshowsstore.com by moviet on Mar 18, 2010

483 1984

Last Topic: I have upgraded and I cant login! by Aleksandar on Mar 18, 2010

19 69

Last Topic: Custom main index page by Richard on Feb 7, 2010

11 22

Last Topic: Monthly Calendars Help Needed by joe leblanc on Jan 19, 2010

91 326

Last Topic: SpamLookup Keyword Filter 2.1 not work by b.n09 on Nov 17, 2009

55 206

Last Topic: URL Problems by NoSnaiL on Mar 17, 2010

code.sixapart.com

129 449

Last Topic: Action Stream for Google Buzz by jack lail on Feb 16, 2010