Upgrading Plugins with Support for Movable Type 4 and 5


Published on March 4, 2013 at 2:33 PM EST
In the Discussions category.

A lot of plugins were developed for Movable Type 4. Some of those plugins work with MT5 (such as plugins that add modifiers), however many are incompatible. Upgrading plugins to add support for MT5 is not the most straight-forward thing, so I’ve been keeping some notes about my progress; hopefully these tips are helpful to others, too.

The topics covered:


Version-Specific Content

I’ve found many templates can still use much of the same HTML and MTML between both versions of MT. A simple <mt:If> statement makes it easy to serve a specific piece to each version of MT. In the following example, the MT5 code sends the user to a page built with the Listing Framework while the fallback MT4 link sends them to the traditional app:listing screen.

<mt:If tag="Version" like="/^5/">
    <a href="<mt:Var name="script_url">?__mode=list&_type=zencoder_profile">
<mt:Else>
    <a href="<mt:Var name="script_url">?__mode=zencoder.profile_list">
</mt:If>

Form Elements

Movable Type versions 4 and 5 use some different class names to format form items. Adding the correct class names for both versions is an easy way to make the form element look correct in both version. For example, a text input in MT4 uses the class “full-width” to fill the width of the available screen space; in MT5 the class is “full”. The following example uses both class names to display the field properly in each version of Movable Type:

<input id="text-field"
    type="text"
    name="text-field"
    value="<mt:Var name="text_field" escape="html">"
    class="full full-width" />

Textareas use the class “full-width” in MT4, and “text full low” in MT5:

<textarea id="question"
    name="question"
    rows="3"
    class="text full low full-width"><mt:Var name="question" escape="html"></textarea>

Movable Type 4 uses <button /> elements for all of the buttons (such as “Save” and “Delete”). Movable Type 5 only uses <button /> for form actions. Any other type of button (such as for a custom field) must be an <a /> in MT 5. Perhaps coincidentally, MT4 also displays <a /> buttons very nicely with the right classes. MT4 uses the classes “button” and “primary-button” for formatting; MT5 uses the classes “action button” and “action primary button” for formatting.

So, the following form action button displays correctly and functions properly in both MT4 and 5:

<button
    mt:mode="pp_save"
    type="submit"
    accesskey="s"
    title="Save this poll."
    class="action primary button primary-button"
    ><__trans phrase="Save Changes"></button>

And the following works as a button that should not trigger a form action (such as for a custom field) in both versions, too:

<a
    onclick="alert('test');"
    class="action button">
    Choose entry
</a>

“Undefined Subroutine” Errors

Some core functions have moved in MT5. If your plugin throws this error, it’s likely that the function have been moved to another module in MT5.

Building Menus

Menus changed a lot between Movable Type 4 and 5. In MT4 are the Create, Manage, Design, Preferences, Tools, and System Overview menus. In MT5 menus are more focused on objects, with a few other menu types thrown in: Entries, Pages, Assets, Tags, Settings, Tools, Blogs, Websites, Listing Filters, and several more.

In both version of MT, the parent meu must exist in order to add a child item. In other words, a “Preferences” menu must exist to add a new menu item called “My New Preference.” So, installing the Create and Manage menus to MT5 will add back menu items that a plugin added there; the Create and Manage plugin from Movable Tips makes this easy.

Of course, in both version of Movable Type adding to the menu is simple: a set of registry keys will add an item, and as long as the correct menu is targeted the menu item appears. Both version of Movable Type can be targeted in a single plugin, as in this example, excerpted from ImageCropper:

applications:
    cms:
        menus:
            # MT5 compatibility: add to the Settings menu
            settings:image_cropper:
              label: Thumbnail Prototypes
              mode: list
              args:
                  _type: thumbnail_prototype
              order: 500
              view: blog
            # MT4 compatibility: add to the Preferences menu
            prefs:image_cropper:
              label: Thumbnail Prototypes
              mode: list_prototypes
              order: 500
              view: blog

Listing Framework

Using Movable Type 5.1 as a minimum requirement is a good idea because that is when the Listing Framework was released. The Listing Framework brings sortable, filterable, customizable listing screens not just to the default Movable Type objects (such as Entries, Assets, and Users) but also to any plugin that wants to levy those features. A great advantage over the old app:listing tag!

In the Menu registry keys above, note that there are some different values for the mode and args. MT4 users still see the traditional listing screen you’ve already built for your plugin; MT5 users see a listing screen built with the Listing Framework and get to take advantage of all the benefits it offers.

As the developer’s guide for the Listing Framework shows, there are a number of registry keys used to build and control the listing screen.

Adding a listing screen is easy with a few registry keys (excerpted from Poll Position):

listing_screens:
    pp_questions:
        primary: 'title'
        default_sort_key: 'created_on'

Next, populate the new screen with list_properties. List properties define the columns of the listing screen and what content is displayed in them, and a number of keys are used to build them as necessary. Honestly, some of the complexities and capabilities of listing properties are still a mystery to me even after referring to how the native MT objects are built, but getting started is quite easy.

list_properties:
    pp_questions:
        id:
            base: '__virtual.id'
            order: 100
        title:
            base: '__virtual.label'
            label: 'Title'
            order: 200
            display: 'default'
        created_by:
            base: '__virtual.author_name'
            order: 600
            display: 'default'
        created_on:
            base: '__virtual.created_on'
            order: 700
            display: 'default'

Hunting down an appropriate base is integral to getting the column to work correctly. __virtual.string is often a good starting point and specifying the col key (with the column’s basename) is essential for making a sortable column. Also, when in doubt, try the auto key, which will try to work everything out on its own.

Default filters can be created for your listing screen, too. System filters are poorly documented so referring to examples in the core objects is the best way to learn about them.

system_filters:
    pp_questions:
        polls:
            label: 'Polls'
            order: 100
            items: 
                -
                    type: 'type'
                    args:
                        string: 'poll'

More complex system filters and list properties (such as those that combine the results from multiple tables) appear to use summary tables, which also are not documented well.

The familiar list_actions are used to add actons to the Listing Framework. These work as they did with MT4, however there are some new capabilities. In particular, I’ve found the button key to useful.

It’s worth noting that the Listing Framework does not work in popup dialogs.

Both versions of Movable Type use a popup dialog to help users interact with content — most notably, perhaps, is the File Upload dialog. The dialog is accessed differently in each version of MT. In MT4, the Javascript functions openDialog() and closeDialog() are used. In MT5, the dialog can be called by simply uses the classes “mt-open-dialog” and “mt-close-dialog” (in a link, for example), or with a Javascript function.

So, in MT4 you might have used something like this:

<button
    onclick="openDialog(this.form, 'my_mode', blog_id=1...');"
    class="primary-button">Test the popup dialog</button>

In MT5 the same can be done like this:

<a
    class="mt-open-dialog action primary button"
    href="test-page.html">Test the popup dialog</a>

A Javascript function can also be called in MT5:

<a
    onclick="jQuery.fn.mtDialog.open('test-page.html');"
    class="action primary button">Test the popup dialog</a>

Closing a dialog is also easy: create a button that uses the class “mt-close-dialog”. If using the Javascript function, call parent.jQuery.fn.mtDialog.close(); (note the parent use, because the main page — not the dialog itself — must close the dialog).

Object Listings in Popup Dialogs

As noted above, the Listing Framework’s capabilities don’t work in popup dialogs. Object Listings aren’t used too much in MT4 and I suspect they are used more extensively in More Custom Fields than they are used in the core. Object Listings in MT4 are something of a specialty item and are constructed from HTML and MTML without the app:listing tag. It’s no different in MT5, however the table structure has changed, using a separate table for the header/footer and body of the object listing. More Custom Fields’ entry_list.mtml is such a listing and it does work for both MT4 and 5 (object listing, search, and pagination) though it’s long, complex, and not pretty. If you need to create an object listing, the More Custom Fields entry_list.mtml is probably the best example there is.


Hopefully all of these tips from my experience help others get started and successfully wade through the details necessary to add version 5.x compatibility to their MT plugins.

This upgrade guide was written by Dan Wolfgang for Endevver after completing some plugin upgrade projects, as a way to document and share some of my experience with the effort required to upgrade plugins.

This article is tagged as: Listing Framework, MT4, MT5, Plugins, Upgrade