Not a developer? Go to MovableType.com

Documentation

Theme Framework from plugins

This page describes how to extend theme framework for plugins.

Theme package and Theme framework

Theme Package

Theme data that can be used in Movable Type. Define themes with plugins or by storing them in the themes directory.

Theme Framework

Refers to the framework for the input/output of Theme Package data in Movable Type. By extending Theme Framework, plugin developers can make their plugin data usable with a Theme Package.

Each theme field in the Theme Package is defined as a Theme Element. Importer and Exporter handle the reading and writing of Theme Elements. Plugin developers can extend the data structure of Theme Elements in the Theme Package by implementing Importer and Exporter.

Importer and Exporter

Importer is required to use Theme Elements in Movable Type.

Exporter is required to export themes from Movable Type’s admin screen. However, as long as you don’t export themes from existing websites or blogs, Exporter is not required. Theme designers still can include the theme element manually referring the Importer specifications.

How to add Importer/Exporter

You must prepare a Perl routine for Importer. Add the following to plugins:

  • Perl sub-routines to handle the import process
  • Registry entry to register the import handler

Add to Registry

This is an example yaml to register registries.

theme_element_handlers:
    my_element_handler:
        label: My Element Handler
        importer:
            import: $MyPlugin::MyPlugin::Theme::apply
            info: $MyPlugin::MyPlugin::Theme::info
            validator: $MyPlugin::MyPlugin::Theme::validator
        exporter:
            params: custom_fields_export_ids
            component: my_plugin
            condition: $MyPlugin::MyPlugin::Theme::condition
            template: $MyPlugin::MyPlugin::Theme::template
            export: $MyPlugin::MyPlugin::Theme::export

Importer

Importer and Theme Element work on a one-to-one basis. When you apply a theme to a website or blog, Movable Type looks for Importer for all the Theme Elements in that particular theme, and begins processing. Actual import processes should be implemented in the importer.

If Importer isn’t found, and that particular Theme Element isn’t necessary, it will be ignored and the theme will be applied. If that particular Theme Element is necessary, processing will stop and an error notice will be sent to the user.

import

Specify the Perl sub-routine that applies the theme. Movable Type sends the following three parameters to sub-routines.

  • The Theme Element that is applied.
  • The entire theme including the Theme Element.
  • The (often just created) MT::Blog or MT::Website Instance where the theme is applied.

The Theme Elements and overall Theme are each passed along as objects blessed with MT::Theme::Element and MT::Theme class. Here is an example of an importer that applies Theme Elements embedded with each blog setting to MT::Blog class.

sub my_importer {
    my ( $element, $theme, $obj_to_apply ) = @_;
    my $data = $element->data;
    if ( ref $obj_to_apply ne MT->model('blog') ) {
        return $element->errtrans('this element cannot apply for not blog object.');
    }
    my $blog = $obj_to_apply;
    for my $conf ( keys $data ) {
        if ( $blog->has_column($conf) ) {
            my $value = $data->{$conf};
            $blog->$conf($value);
        }
    }
    return 1;
}

info

This is a sub-routine for analyzing the content of themes. Displays a message to users describing what takes place when the theme is applied.

sub info {
    my ($element, $theme, $blog) = @_;
    my $item_count;
    ## analyse the $element and set some value for $item_count
    return sub {
        MT->translate(
            '[_1] items would be added to your blog.',
            $item_count,
        );
    };
}

validator

Tests the current blog and assigns a sub-routine that determines whether the Theme Elements is acceptable.

sub validator {
    my ( $element, $theme, $obj_to_apply ) = @_;
    my $conflict;
    ## validate $obj_to_apply is okay to apply $element.
    if ( $conflict) {
        return $element->error(
            MT->translate(
                'Conflict has occurred!',
            )
        );
    }
    return 1;
}

Exporter

params

When you export a theme, set the name of the parameters to be used on the Options setting screen. MT holds export settings based on this value. Use Array_ref to make settings if you’re using multiple parameters.

component

Set the ComponentID for the importer that imports exported data.

template

Set the output sub-routine on the Export Options setting screen.

sub export_template {
    my $app = shift;
    my ( $blog, $setting ) = @_;
    $setting = { some_setting => 'default' }
        if !defined $setting;
    my $param = $setting->{some_setting};
    my %param = (
        param_for_tmpl => $param,
    );
    return $app->load_tmpl(
        'include/my_export_screen.tmpl',
        ¥%param,
    );
}

export

Set the sub-routine where exporting actually takes place.

sub export {
    my $app = shift;
    my ( $blog, $setting ) = @_;
    my $export_data = {};
    ## do copy some data from $blog to $export_data
    return $export_data;
}

Please have the export sub-routine return a hash reference. This return value is stored as exported Theme Element data.

finalize

Set a sub-routine to run after exporting is complete. The sub-routine you assign here is called after theme data is successfully created and a temporary directory for export processing is secured. You can conduct operations on the theme directly, such as copying files.

sub finalize {
    my $app = shift;
    my ( $blog, $theme_hash, $tmpdir, $setting ) = @_;
    my $success = 0;
    ## some work for $tmpdir
    return $success ? 1 : 0;
}

condition

Set the sub-routine that determines whether or not you can use export handler on the website or blog that exports the theme. For example, decide not to display category export options for blogs without categories.

sub condition {
    my ( $blog ) = @_;
    # show export option if blog has at least one template.
    my $tmpl = MT->model('template')->load(
        { blog_id => $blog->id },
        { limit => 1 },
    );
    return defined $tmpl ? 1 : 0;
}

versioning

Theme Package and Importer each have two version settings, for a combined total of four.

  • Theme Package
    • schema_version
    • min_importer_version

  • Importer

    • min_schema_version
    • max_schema_version

min_schema_version <= schema_version <= max_schema_version

If Theme_Package’s schema_version fits between Importer’s min_schema_version and max_schema_version, the theme will be successfully applied.

schema_version < min_schema_version

If the plugin has been upgraded to a newer version, however, Importer won’t be able to apply an old theme. If the Theme Package’s schema_version is lower than the Importer’s min_schema_version, Movable Type will either skip processing this Theme Element and continue applying the theme, or cancel the entire process, depending on whether the Theme Element is necessary or not. However, we recommend plugin authors check the Theme’s schema_version, enter appropriate alternate values, etc to ensure downward compatibility.

max_schema_version < schema_version

The Theme Package’s schema_version may also be larger than the Importer’s max_schema_version. You may attempt to use an old plugin to import a Theme that was exported with a new plugin. In this case, use the min_importer_version specified in the theme creator’s Theme Package. Movable Type will tell users they need to upgrade the the plugins to use the theme, and either continue applying the theme or halt application.

It is recommended to set the following values:

  • Theme Package
    • schema_version
      Specify newest version at time theme is created
    • min_importer_version
      Specify which version of Importer can be loaded if this theme cannot load old Importers when this theme is being created

  • Importer

    • min_schema_version
      Specify theme’s Schema_version that can be loaded if this Importer cannot load old theme when this Importer is being created.
    • max_schema_version
      Define newest version when creating Importer

The most important thing is to secure downward compatibility at all times. If Importer can read all the versions of the Theme Package, you can simply write the newest version in the Theme Package’s schema_version and Importer’s max_schema_version.

Back