Movable Type Plugin: Template Callbacks --------------------------------------- This is a proof-of-concept plugin. It tries to re-define the relations between templates, plugins and themes. 1. It defines the concept of 'Callbacks' inside a template 2. let the theme declare 'theme variables', that are added to the templates on build 3. Opens the ability for content-plugins The theme variables can be set under the Design->Appearance menu It works for Static Publishing and Dynamic Publishing ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Plugin Template Init -------------------- For initializing the plugin, put in the head of each published template (either index or archive) the following tag: <$mt:InitTemplateCallback screen="screen_name"$> At the start of the template, please add these lines: The screen name specifies in which page we are now. typlically is "main_index", or "entry" and so on Without this tag, the callback tags will be ignored, and the theme variables won't be added to the template variables ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- TAGS ---- If offers three tags: <$mt:TemplateCallback name="callback name" [priority="5"] $> This runs all the callbacks for the given name. Examples for names: "verytop", "siderbar_primary sidebar_secondary". Priority: can be either a number, (i.e. "5") or a range ("3..7"). Will execute only the callback with these priorities. If no priority is given, will execute all the callbacks for this callback name. <mt:SetTemplateCallback name="callback name" [priority="5"] $> ... template code ... </mt:SetTemplateCallback> This set a callback for a given name, and priority. If no priority was given, 5 is the default. <mt:AreCallbacksRegistred name="callback name"> </mt:AreCallbacksRegistred> A conditional block, running only if any callback was registered for this name. Callback Names -------------- A typical callback name is: "publish.verytop.index". It goes from the application, to the position, and to the specific page name. In this case, callbacks registered to the following names will be run: "publish", "publish.verytop" and "publish.verytop.index". So callback registred to "publish.verytop" will appear in the very top of all the pages. Registering a global Callback ----------------------------- In your plugin directory, create directory: "tmpl/callbacks". In this directory, the files sould be named "<cb_name>.<priority>.tmpl". i.e. publish.sidebar_primary.2.tmpl Will register a callback for all blogs, callback name "publish.sidebar_primary", priority "2". Another example: publish.banner.entry.5.tmpl Will be added to the banner only in the entry pages, with priority "5". Registering a Callback on the DB -------------------------------- Create and save a template object, with the following parameters: my $tmpl = $app->model('template')->new(); $tmpl->type('t_callback'); $tmpl->name('verytop.entry'); $tmpl->blog_id(0); $tmpl->text('<h1>this is a callback</h1>'); $tmpl->build_interval(5); $tmpl->identifier('publish'); $tmpl->save() or die "failed to save tmpl"; Notes: * Name can also be "plugin_id::verytop.entry", which will be activated only if the plugin is installed. * "blog_id" can be "0" or a specific blog number. * The identifier specify for which application this callback is directed. currently, only 'publish' exists. If this callback is setting-dependent, you can do it on setting-saving, in the following callbacks: callbacks: MT::PluginData::pre_save: $Plugin::Module::plugin_data_pre_save save_config_filter.Plugin_Id: $Plugin::Module::register_callbacks Where the first callback will work for older MT installations, and the second is prefered for new MT versions. Widgets ------- The widgets are automatically loaded into these callbacks: "publish.sidebar_primary" and "publish.sidebar_secondary", with priorities from "3" to "7". If there is only one sidebar, they will be mixed together, ordered by priority. Note: this is the only case of callbacks with non-integer priority. oops. The "mt:widgets" tag has another attribute: "callback". It is the name of the callback to load the widgets on, and to excecute. If there are more then one callback in the attribute, the widgets will be loaded on the first callback, and all the callbacks will be excecuted. Examples: <$mt:WidgetSet name="<__trans phrase="3-column layout - Primary Sidebar">" callback="sidebar_primary"$> <$mt:WidgetSet name="<__trans phrase="2-column layout - Sidebar">" callback="sidebar_primary sidebar_secondary"$> If a callback attribute is not present, the widgets will be displayed normally, and no callback will be called. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Declaring Theme Variables ------------------------- In the theme.yaml file, under the 'elements' key, add the following lines: elements: variables: component: TemplateCallback importer: theme_variables data: background_color: order: 100 label: Background Color type: color default: red This defines one variable, of type 'color', with label and default. All these keys are required. (order, label, type and default) there might be other types that need / can accept more keys. Declaring Color Theme variable ------------------------------ Good for: background color, banner color, font color, and so on background_color: order: 100 label: Background Color type: color default: red the default can be either a CSS color name, or in hex format, i.e. #330099 Declaring Image Theme variable ------------------------------ Good for: banner image, user picture banner_image: order: 200 label: Banner Image type: image default: '%ss/banner.jpg' size: 'w:940 h:198' The default image should be part of the theme, and must be of the expected size If it is under the 'static' directory, it should start with "%ss/". If it is under the 'blog_static' directory, it should start with "%bs/" If the user supplies an image that does not fit the expected size, it will be scaled to the requied size. (TODO: make something more advanced then that) Declaring Checkbox Theme variable --------------------------------- Good for: yes/no questions is_up: order: 300 label: Is Up? type: checkbox default: 1 the default should be 1 or 0 Declaring Radio button / Dropdown Theme variable ------------------------------------------------ Good for: multiple options, such as in which side to put the widgets, different layouts and so on. which_side: order: 400 label: Which side type: dropdown default: up choices: up: Up down: Down left: left right: Right the default should be one of the choices. In the choices, the user is displayed the values, and the theme variable contains the key. So in this case, the user will select 'Down', and the 'which_side' variable will contain 'down'. putting 'radio' instead of 'dropdown' will create radio buttons. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Content Plugins --------------- This gives plugins the ability to have plugin-data inside the body of an entry, that will be inflated to true HTML code when the entry is published (on static publishing) or viewed (on Dynamic Publishing) For this to work, the plugin needs to add to the body the following HTML code: <div class="mtplugin mtplugin_<plugin name>"> <div class="plugin_internal_data" ...attributes...> ...plugin data... </div> </div> Anything that is inside the mtplugin div, but outside the plugin_internal_data div is considered edit-time information and will be discard on save. So you can add controls and previews, that will not be showed on the published entry. For registering the publish-time replacement, add in your config.yaml file: tags: content: <plugin name>: $Plugin::Perl::Module::handler If a matching div is found in the entry one publish, this handler will be called using these parameters: $str = handler($app, $ctx, $plugin_name, $content, \@args) Where $content includes whatever was inside the plugin_internal_data div, and @args contains pairs of [key, value] of the attributes of the same div The whole mtplugin div will be replaced with the output of the handler function. If there is no such handler function registered, the div will be deleted. Controling the plugin divs replacement -------------------------------------- By default, these plugins will be only active for the EntryBody, EntryMore tags and their Page equivalents. However, you can turn this on for other tags as well using this modifier: content_plugins="1" Also, for the EntryBody/More tags, setting it to zero will disable the plugin operation: content_plugins="0" ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Included Themes --------------- The attached themes are a copy of the "classic blog" and "website" themes supplied by default with Movable Type. They were modified to support callbacks. The following callbacks are used: before_content, after_content, above_footer, footer, verybottom, verytop, banner, below_banner, htmlhead, between_content.entry_summary, sidebar_secondary, sidebar_primary, after_content, before_content The following screen-names are used: archive_index, category_entry_listing, comment_preview, comment_response, dynamic_error, entry, main_index, monthly_entry_listing, page search_results. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- TODO ---- In Dynamic Publishing, add support for ignoring callbacks from plugins that were uninstalled or deactivated.
shmuelfomberg/mt-plugin-template-callback
Adding Template Callbacks feature - proof of concept
JavaScript