Not a developer? Go to MovableType.com

News

Movable Type Registry Reference

By Byrne Reese
Posted June 8, 2007, in Documentation / Developers / Registry Reference.

Frequently in this manual certain conventions and terminology will be used in reference to specific design and implementation patterns. In lieu of defining these constructs and conventions over and over again, they are defined below. Familiarizing yourself with these concepts and terms will greatly enhance your ability to understand the contents of this reference manual.

Registry Syntax

Registry configuration files are expressed in YAML syntax. YAML is a simple, lightweight markup language for representing simple data structures in a platform and language independent way. For more information about YAML's syntax, visit its homepage.


Data Type

scalar

Then the type SCALAR is specifically defined for a registry key or item, which is the default value for all registry keys, then there can be one and only one value associated with the key. If an item is added to the registry for which their is already a corresponding name/value pair, then the value of the item being added will overwrite the previous value.

array

When the type ARRAY is specifically defined for a registry key or item, then the value of that registry item is assumed to have multiple values. If an item is added to the registry for which their is already an existing name/value pair then the new value and the old values are aggregated into a single array. Consequently, it means that developers should assume that the value of such a registry item is an array and can be accessed using Perl's array syntax.

Example

   $registry = {
urls => [
'http://somedomain.com/foo',
'http://somedomain.com/bar',
'http://somedomain.com/baz',
],
};

Is equivalent to:

   $registry = {
urls => 'http://somedomain.com/foo',
urls => 'http://somedomain.com/bar',
urls => 'http://somedomain.com/baz',
};

hash

A "hash" refers generically to any collection of related key/value pairs. In that way the registry itself is a hash that contains other hashes. When the type HASH is specifically defined for a registry key or item it therefore means that its value a slightly more complex data structure containing a sequence of name/value pairs.

Example

   $registry = {
permissions => {
'system.create_blog' => {
label => trans("Create Blogs"),
group => 'sys_admin',
order => 100,
},
},
};



handlers

A handler is a function to which events are passed for processing. The value of a handler is a coderef.


coderefs

A "coderef" is the means by which a developer can reference a block of code that needs to be executed by the framework. A coderef can be expressed in the following ways:

  • As a fully qualified function name, e.g. "&function_name" and "MT::ComponentName::function_name".
  • As an inline code block and anonymous subroutine, e.g. "sub { code goes here }".

Registry Keys

   $registry = {
permissions => {
'system.create_blog' => {
label => trans("Create Blogs"),
group => 'sys_admin',
order => 100,
},
},
};

name

The name of the component being registered.


class

The package name of the component being registered. The package being referenced should contain all the business logic for the component being registered. This package is automatically loaded when Movable Type initializes itself and all of its components.


author

The name of the author of the component.


version

The `version` registry key stores the version number of the plugin or component being described. This value is used to display to a user, and is used to determine if newer versions of this plugin or component exist.

The value of `version` should be any valid positive floating point number and should not contain and letters or special characters.

Sample Values

  • 1.0
  • 2.05
  • 0.03
  • 0.45a invalid
  • version 3 invalid
  • 1.42.1 invalid

schema_version

For those components that have custom data types that they define, it is highly recommended that they also define a `schema_version`. The `schema_version` is used by Movable Type to determine if changes are required to the structure of database when new components or plugins are installed. Each time Movable Type is loaded, the schema version of the database is compared to that of each component is compared to what is declared and stored within the system. If the declared schema version is greater then what is on record for that component, Movable Type begins the upgrade process to bring the schemas in sync.

The `schema_version` should be a simple integer, but can be a floating point number to indicate minute changes to the schema. Each time the schema for a component or plugin changes, the `schema_version` should be incremented.


object_types

Plugins and components may need to persist information into a database. Therefore, database tables need to be defined and generated within Movable Type's database. These tables are created and maintained for each registered "object type" in the registry. Movable Type's core even utilizes this framework to keep its own database up to date from release to release of the core platform.

The value of `object_types` is an array of keys, where the name of each key is the name of the data type being registered. The value then associated with each key is a package name where the complete definition of the object or class can be found. The package then contains specifics about the structure of the data in the database, in addition to all the business logic associated with the object.

See also: MT::Object man page. (TODO)

Example

   $registry = {
version => MT->VERSION,
schema_version => MT->schema_version,
object_types => {
'foo' => 'MT::Foo',
'bar' => 'MT::Bar',
},
};

MT::Foo.pm

   package MT::Foo;
use strict;
__PACKAGE__->install_properties({
column_defs => {
'id' => 'integer not null auto_increment',
'blog_id' => 'integer not null',
'title' => 'string(255)',
'text' => 'text',
},
});

Extending Existing Object Types

Movable Type allows object types to be extended. This allows plugins and components to insert and associate additional pieces of data with a pre-existing data type. Furthermore, these additional pieces of data become a seamless extension of the original data element, allowing that object to be sorted by and filtered by the new data element quickly and easily.

Extending an object is done by declaring the extension within the registry. For example, to add a new "ratings" field to the core entry object for the purposes of allowing users to attach a zero to fives star rating to entry, one would do the following:

   $registry = {
object_types => {
'entry' => {
rating => integer,
},
},
};

Whenever a component or plugin declares an object type that already exists, the that object_type declaration acts as an extension to the pre-existing object type. Remember, if a plugin or component every changes an object type it declares, or changes the nature of an extension to a pre-existing object type, the schema_version associated with that plugin or component should be incremented to signal to Movable Type that some database maintenance may be required.

object_drivers

This feature is documented, but not currently used.

Movable Type comes with support for a number of different databases including (but not necessarily limited to) MySQL, Postgres and SQLite. Furthermore, support for Oracle and Microsoft SQLServer is provided through an additional add-on, called the "Enterprise Connectivity Pack." Support for these databases and others is provided through "object drivers." Object drivers provide a database framework for:

  • creating database tables during installation
  • maintaining database tables during an upgrade
  • generating SQL statements for a set of standard queries during normal operation

Evaluating Support for Custom Object Drivers

Some developers may wish to bind Movable Type in someway to a currently unsupported database or backend storage system. In order to determine if such a system can be compatible with Movable Type's object driver system, make sure backend system meets the following minimum requirements:

  • perform simple CRUD (create, read, update and delete) operations
  • supports indexing specific fields
  • supports the joining of two tables

permissions

Movable Type allows plugins and components to generate custom permissions that can be assigned to users. Permissions registered in this way will automatically appear within the user interface allowing administrators to immediate begin assigning that permission to users and roles.

The value associated with the `permissions` registry key is an array of permissions being defined. Each permission being registered in this way is itself a hash which defines the specific parameters governing the display and usage of that permission within the application.

Permission Properties

Permissions within the registry support the following properties:

  • label - The name of the label as it should appear when displayed to the user.
  • group - The permission group the permission should be displayed within. Valid values are:
    • sys_admin
    • blog_admin
    • auth_pub
    • blog_design
    • blog_upload
    • blog_comment
  • order - The sort key for your permission to customize where the permission is displayed relative to other permissions.

Note: permissions within the registry are not automatically rendered and made available through the user interface to be assignable by an admin. For the time being that must be done with a transformer callback.

Permission Scope

Permissions can be defined to operated within two different scopes: a blog specific scope or a system wide scope. The scope of a permission is specified by prefixing the permission's unique id or name with either "blog" or "system" followed by a period (".").

For example, to register a custom permission, use the following syntax.

   $registry = {
permissions => {
'system.create_blog' => {
label => trans("Create Blogs"),
group => 'sys_admin',
order => 100,
},
},
};

config_settings

Movable Type provides developers with two mechanisms for configuration of their software. The most basic form of configuration is through Movable Type's configuration file, or `mt-config.cgi`. Movable Type's configuration file is in some cases a preferred mechanism for configuration due to the following reasons:

  • ease of implementation
  • configuration options do not clutter the user interface

When parsing `mt-config.cgi` Movable Type will validate the directives found there and produce an error if it encounters something it doesn't understand. Therefore, developers must declare their configuration directives by registering them with Movable Type.

   config_settings => {
'AtomApp' => {
type => 'HASH',
default => 'weblog=MT::AtomServer::Weblog'
},
'DefaultEntryPrefs' => {
type => 'HASH',
default => {
type => 'Default', # Default|All|Custom
button => 'Below', # Above|Below|Both
height => 162, # textarea height
},
},
'DefaultLanguage' => {
default => 'en_US',
},
},

Configuration Setting Properties

Configuration settings have the following properties.

  • type - The data type of the value the configuration setting contains, valid values are "HASH," "ARRAY" and "SCALAR." The default is SCALAR.
  • default - The default value of the configuration setting if an explicit setting cannot be found.
  • path - A boolean value (1 or 0) to indicate whether the value contains a path or not. TODO - what does it do if it is a path? Used by MT to convert relative paths into full paths. Takes the values and converts into a full path relative to the location of the mt-config.cgi file.

Examples:

   PluginSwitch foo=bar
PluginSwitch baz=boo
Schema 1
Schema 2
Goozer abc

text_filters

Text filters provide the means by which text being published to the blog can be transformed in some way just prior to being published. Filters can either be associated with an entry so that its contents are automatically transformed, or they can be invoked directly via an attribute placed within any template tag. The key for any filter also serves as the text filter's unique name.

text_filters => { 'my_filter' => { label => 'Transform this Text', handler => 'MT::Foo::text_transform', }, }

To learn more about how to create a text filter, see TODOText Filters.

Global Text Filters

A global text filter is a filter that is performed upon the value of any template tag using a special attribute. To learn more about global text filters, see: "tags."

Text Filter Properties

  • label - The display name for the filter.
  • handler - A reference to a subroutine that handles the actual transformation.

See also: How to create a text filter.

In Progress:

applications

Movable Type allows developers to define and create their own applications embedded within the core application that utilize the Movable Type platform for defining custom permissions, database management, et al. These application often require their own highly customized user interface.

To facilitate the creation of these highly customized user interfaces, developers can define an "application" within the registry. Each registered application can define the following:

  • its own private set of list filters
  • its own set of menu items that are listed in Movable Type's built in menu system
  • its own set of handlers for processing commands dispatched via the web interface

Application Properties

  • handler - The package name that will process calls dispatched via the web interface.
  • cgi-base - Not currently used. It identifies the name of the CGI file without the .cgi file extension. It is used for URL construction.
  • list_actions - A list action is an action performed on a number of entries at a single time. Permitted values include: entry, page, asset, commenter, author, role and group.
  • page_actions - A page action is a simple link that is surfaced in association with a given object.
  • menus - A list of menus and menu items to add to the application.
  • methods - A list of modes (or "commands") and their associated handlers for processing requests to the application.

How to Add a Mode to the CMS Component

To register a mode in an existing application use the code below.

Example

   $registry = {
applications => {
'cms' => {
methods => {
myapp_new-mode => sub { // my handler // },
},
},
},
};

Tips and Best Practices

The ease with which new modes are added to the "cms" application, the default MT app, makes it tempting for developers to never define their own applications, and to always add new modes to cms. However, developers of complex plugins are encouraged to create their own applications for more complex plugins. Furthermore, when adding modes to a pre-existing application, developers are encouraged to prefix their modes with a unique identifier of some kind to help prevent namespace collisions in the future.

CMS Application Specific Stuff

Movable Type's core defines the "cms" application. This application supports its own set of registry keys. One such registry key allows users to define custom import formats to allow users to easily take content from one application and import it directly into Movable Type.

  • import_formats - The value of the import_formats key is an array of hashes that define each supported import type and format. Each import type is a hash itself which has the following keys:
    • label - The name of the format being imported as it will displayed within the user interface
    • code - The handler for processing the import file
    • options - The input keys for import type specific configuration options.
    • options_template - The file that contains the HTML and template code for rendering the custom configuration options for the import type.
   import_formats => {
'import_mt_format' => {
label => 'Another system (Movable Type format)',
code => \&MT::ImportExport::import,
options => [ 'title_start', 'title_end', 'default_status' ],
options_template => 'import_others.tmpl',
},
},
},

Example

   applications => {
'ack' => {
handler => 'MyApp::Ack',
cgi_base => 'ack',
list_actions => {
'entry' => {
'do_something' => {
label => "Batch Do Something",
order => 100,
code => \&do_something,
permission => 'edit_all_posts,publish_post',
},
},
menus => {
'foo' => {
label => "Create",
order => 100,
},
'foo:bar' => {
label => "Do Something",
order => 100,
mode => 'hdlr_bar',
args => { _type => 'entry' },
permission => 'create_post',
requires_blog => 1,
},
},
methods => sub { MT->app->core_methods() },
},
};

List Actions

Page Actions

Import Formats

callbacks

For defining callbacks.

tasks

Movable Type provides a framework for registering frequently occurring tasks, or tasks that must occur on a fixed schedule. These tasks are managed in of two ways:

  • by a script run externally to the Movable Type web application
  • by the web application when the LaunchBackgroundTasks setting is set in the mt-config.cgi file

A plugin declares a new task in the registry using the following code:

tasks => { 'FuturePost' => { key => 'FuturePost', label => 'Publish Future Posts', frequency => 15 * 60, # no more than every 15 minutes code => sub { MT->instance->publisher->publish_future_posts; } }, }

Task Properties

  • key - a unique identifier for the task
  • label - the display name for the task, as it will appear in the activity log and elsewhere
  • frequency - the number of seconds to wait between each time the task is run
  • code - the handler or callback that will be invoked when the scheduled task runs

TODO: What does it mean when a template tag is prefixed with "App:" - I can guess, but how should I explain it? They are namespaced just to communicate scope. No functional implications.

junk_filters

list_filters

   entry => {
published => {
label => 'Published entries',
order => 100,
handler => sub {
my ( $terms, $args ) = @_;
$terms->{status} = 2;
},
},
received_comments_in_last_7_days => {
label => 'Entries with comments in the last 7 days',
order => 500,
handler => sub {
my ( $terms, $args ) = @_;
my $ts = time - 10 * 24 * 60 * 60;
$ts = MT::Util::epoch2ts( MT->app->blog, $ts );
$args->{join} = MT::Comment->join_on(
'entry_id',
{ created_on => [ $ts, undef ], },
{ range_incl => { created_on => 1 }, }
);
$args->{sort} = \'comment_created_on';
$args->{direction} = 'descend';
},
},
},



upgrade_functions

   upgrade_functions => {
'core_create_placements' => {
version_limit => 2.0,
priority => 9.1,
updater => {
type => 'entry',
label => 'Creating entry category placements...',
condition => sub { $_[0]->category_id },
code => sub {
require MT::Placement;
my $entry = shift;
my $existing = MT::Placement->load({ entry_id => $entry->id,
category_id => $entry->category_id });
if (!$existing) {
my $place = MT::Placement->new;
$place->entry_id($entry->id);
$place->blog_id($entry->blog_id);
$place->category_id($entry->category_id);
$place->is_primary(1);
$place->save;
}
$entry->category_id(0);
},
},
},
}

tags

   tags => {
block => {
TagNameFoo => &foo_handler,
},
function => {
TagNameFoo => &foo_handler,
},
modifier => { # attribute only, not a tag name - this is for global filters
TagNameFoo => &foo_handler,
},
}

archive_types

Movable Type enables developers to define their own archive types, allowing them to group and publish articles in custom ways. I good example of a custom archive type is perhaps a collection of entries based on a custom timeframe or other shared attribute.

The structure of an archive_type in the registry is as follows. The value associated with the unique archive_type key is an ArchiveType object.

Archive Type Properties

  • name - the name of the archive.
  • archive_label - the display name of the archive to be used
  • archive_file -
  • archive_title -
  • date_range -
  • archive_group_iter -
  • archive_group_entries -
  • dynamic_template - The file path/pattern to be used under dynamic publishing.
  • default_archive_templates - An array of ArchiveFileTemplates which defines the default file/path structure for pages belong to this archive.
  • dynamic_support - A boolean value (1 or 0) indicating if the archive type supports dynamic publishing.
  • date_based - A boolean value (1 or 0) indicating if the archive type is paginated by date. This will signal to Movable Type that the archive, in addition to what other attribute entries within the archive collection might share, are also segmented by date.

Example

   archive_types => {
'Weekly' =>
ArchiveType( name => 'Weekly',
archive_label => \&weekly_archive_label,
archive_file => \&weekly_archive_file,
archive_title => \&weekly_archive_title,
date_range => \&weekly_date_range,
archive_group_iter => \&weekly_group_iter,
archive_group_entries => \&weekly_group_entries,
dynamic_template => 'archives/week/<$MTArchiveDate format="%Y%m%d"$>',
default_archive_templates => [
ArchiveFileTemplate( label => MT->translate('yyyy/mm/day-week/index.html'),
template => '%y/%m/%d-week/%i', default => 1 ),
],
dynamic_support => 1,
date_based => 1,
),
}

commenter_authenticators

   commenter_authenticators => {
'OpenID' => {
class => 'MT::Auth::OpenID',
label => 'OpenID',
login_form => <<OpenID,
<form method="post" action="<mt:var name="script_url">">
<input type="hidden" name="__mode" value="login_external" />
<input type="hidden" name="blog_id" value="<mt:var name="blog_id">" />
<input type="hidden" name="entry_id" value="<mt:var name="entry_id">" />
<input type="hidden" name="static" value="<mt:var name="static" escape="html">" />
<fieldset>
<mtapp:setting
id="openid_display"
label="<__trans phrase="OpenID URL">">
<input type="hidden" name="key" value="OpenID" />
<input name="openid_url" />
</mtapp:setting>
<input type="submit" name="submit" value="<__trans phrase="Sign In">" />
   </fieldset>
</form>
OpenID
login_form_params => \&_commenter_auth_params,
},
}

captcha_providers

   captcha_providers => {
'mt_default' => {
label => 'Movable Type default',
class => 'MT::Util::Captcha',
}
}

default_templates

Back

1 Comment

Mark Carey

Mark Carey on June 10, 2007, 6:05 a.m. Reply

Under list_actions, it states: “A list action is an action performed on a number of entries at a single time. Permitted values include: entry, page, asset, commenter, author, role and group.” What about comment and trackback (ping)? Are these not supported? Or do these need to be added to the docs?

Byrne Reese

Byrne Reese was previously the Product Manager of Movable Type at Six Apart, where he had also held positions as the Manager of Platform Technology and Product Manager for TypePad. Byrne is a huge supporter of the Movable Type user and developer community. He dedicates much of his time to promoting and educating people about Movable Type as well as building the tools and plugins for Movable Type that are showcased on Majordojo. He contributes regularly to open source; and he is an advocate for open protocols and standards like Atom and OpenID.

Website: http://profile.typekey.com/byrnereese