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, ); }; }
varidator
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; }
How to 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.
Recommended versioning
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
- schema_version
- 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
- min_schema_version
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.