Applications

RightFields 1.21

Spam Prevention

TinyTuring 1.02

Template Tags

CheckLinks 1.2

Collect 1.2

Columnize 1.11

Compare 1.1

DateTags 2.3

DaylightOrStandard 1.1

DropCap 1.1

FilterCategories 1.1

FirstNWords 1.3

GetXML 1.1

Glue 1.1

IfModified 1.4

Loop 1.1

TextWrap 1.1

ExtraFields Plugin for Movable Type

Current Version: 0.6


Don't Use This

ExtraFields is obsolete! Please use RightFields instead.

ABOUT EXTRAFIELDS

Many Movable Type users have wished for the ability to define additional custom fields for entries. A future version of MT may include such functionality. This plugin is a stopgap measure until we have a version of Movable Type that allows custom fields. It lets you define custom fields on a per-weblog basis, by creating one or more SQL tables to store the additional data (this plugin has been designed to work only when using MySQL as your MT backend; see below for more on this).

Some users have managed to add custom fields to their copies of Movable Type by modifying the field definitions within MT. See this page and this thread and this thread. However, this approach has several problems:

  • You have to modify MT's built-in data structure. This could lead to problems with future updates. ExtraFields avoids this issue by using external tables to store data; it doesn't touch any existing MT tables.
  • You have to hack some changes into some of MT's source code files. This could lead to problems with future updates. ExtraFields has the same issue, but I've tried to keep the code changes as small and straightforward as possible, and will endeavor to update this documentation whenever a new version of MT comes out.
  • Whatever changes you make will apply across all weblogs. With ExtraFields, you can define a different set of custom fields for each weblog.

If you have reservations about using ExtraFields, an alternative approach to look into is Brad Choate's Key Values plugin. This plugin lets you use any of MT's existing fields (for instance, the Excerpt field, if you're not using it for actual excerpts) to store pairs of keys and values. The value for a particular key can then be accessed easily from within a template.

In short, ExtraFields is not a perfect solution by any means (please read the Caveats section carefully), and it does take several steps to implement. If you're really hankering for custom fields, though, ExtraFields should get the job done.

Requirements

  • Movable Type 3.16 or 2.661. Actually, ExtraFields should work with any version from 2.21 up, but the positions of the required patches to CMS.pm and edit_entry.tmpl, as described below, are based on the 3.16 and (in parentheses) 2.661 versions of those files.
  • SQL database? ExtraFields was designed to work with MySQL or one of the other SQL database platforms supported by MT as the backend for your Movable Type data storage. However, it has been reported that it does work with Berkeley DB; simply skip step 2 in the Installation procedure below. I have not tried this myself, however.
  • Direct database access. You will need to create one or more SQL database tables to store your extra fields. If your web host has provided a web-based database administration interface such as phpMyAdmin, you can use that; otherwise, you'll need shell access to your web server and the knowledge of how to log on to your database from the command line. You'll also need to know the basics of how to define a table in SQL.

How It Works

The approach used by ExtraFields is straightforward: for each weblog for which you want to define custom fields, you create a table with an entry ID column as its primary key, and as many additional data columns as you want. When you enter data in the custom fields for an entry in that weblog, a row with the same entry ID as the entry is created in the external table. (Note that you can associate multiple weblogs with the same external table. This is all discussed in numbing detail in the Installation section, below.)

Note that if you edit and save an entry but do not enter anything in any of the custom fields, a row will not be created in the external table.

When you delete an entry, the corresponding row in the external table will be deleted.

Caveats

Before you start installing ExtraFields, please look over each of these items. If any of them raises a red flag, maybe ExtraFields isn't for you.

  • To use ExtraFields, you have to make some changes to some Movable Type source code—one of the library modules and one of the CMS templates. If you're uncomfortable doing such a thing, listen to your heart. Also, remember that when you install a future MT update that includes an updated version of either of these files, you'll have to re-patch them (I'll try to keep the patches up to date with the latest version of MT).
  • The data you store in your custom fields currently won't be searched when you do searches with MT's public search interface.
  • Previewing doesn't really work. Please note this. Let's say you're editing an entry, and you edit some of your custom fields, and then hit Preview. If you then hit Save This Entry on the preview page, all will be well. But if you hit Re-Edit This Entry, your changes to the custom fields will be lost. Depending on how extensively you use the Preview feature, this could be quite annoying.
  • Your custom fields won't be included when you export your data. If you expect to have to change servers or otherwise back up and restore your database in the near future, you should probably think twice about using ExtraFields. While it wouldn't be too hard to export and re-import your custom tables separately from the rest of your MT database, it would require a decent working knowledge of SQL.
  • When Movable Type eventually does support custom fields itself, it will presumably store the data in a different way than ExtraFields does. So some conversion will be necessary.
  • ExtraFields is not terribly robust in its present form. For instance, it doesn't perform any validation on the data you enter in the custom fields, or do any special handling for numeric columns. See Future Plans, below, for some other features that are missing and why they're likely to remain missing.
  • In general, if you don't feel at least somewhat confident messing around with Movable Type code, SQL, and plugins, and storing some of your data using a hacked-together method that's unsupported by the authors of Movable Type, please don't use ExtraFields.

Other than that, Mrs. Lincoln, you'll love the play.

Future Plans

As emphasized above, ExtraFields is a stopgap measure, designed to tide us over until we have a version of MT or MT Pro that does custom fields natively. Meanwhile, adding more features would most likely add more steps to the already somewhat cumbersome installation process. For these reasons, it's not likely that ExtraFields will be improved much in the future. But to the extent that it does get updated (by me or by anyone else who'd like to work on it), here are some obvious enhancements that would be nice to have.

  • Patch Search.pm so custom fields will be searched when the user searches for text in entries.
  • Fix the Preview/Re-Edit problem.
  • Create an interface within MT's CMS for editing the custom field configuration.
  • Add the ability to specify a maximum length for a field, make a field required, specify that a field should be numeric, and other validation.
  • Add the option to define a choice list for a field.
  • Improve the interfaces to the ExtraFields modules, making them more object-oriented-esque-ish. The reason it's done the way it's done is to minimize the amount of code that needs to be hacked into CMS.pm, but there's probably a better way.

Contact

Please address questions, comments, bug reports, feature requests, interesting usage examples, etc., to mtplugins [AT] staggernation [DOT] com, or post them in the Plugin Development area of the Movable Type Support Forum.


INSTALLATION

1) Installing the ExtraFields Files

Three of the files included in the ExtraFields download need to be uploaded to certain places within your MT installation.

  • Upload ExtraFields.pl to your plugins directory. If you don't have a plugins directory, create one within your main MT directory.
  • Upload ExtraFields.pm to your extlib directory.
  • Upload EFConfig.txt to your extlib directory. This configuration file now just contains sample config information, which you'll modify in step 3 below.

You don't need to install the EFDebug.pl file into your plugins directory unless you're having trouble getting ExtraFields to work after following the installation procedure (see Troubleshooting below).

2) Defining Your Table(s)

For each MT weblog for which you want to define custom fields, you need to have an additional table in your MySQL database. (Actually, you can use the same external table to store the custom fields for more than one weblog. This is discussed further in step 3 below.)

The naming of the table and the columns within the table is important. First, choose a fairly short, distinctive name that describes the data you're storing. Let's call it datasource. In that case:

  • The table should be named mt_datasource
  • The table should have an integer column named datasource_id, which should be indexed
  • Each additional column name should have the prefix datasource_

You cannot choose a name that will cause your table name to conflict with one of MT's existing tables. These are: mt_author, mt_blog, mt_category, mt_comment, mt_entry, mt_ipbanlist, mt_log, mt_notification, mt_permission, mt_placement, mt_template, mt_templatemap, mt_trackback, mt_tbping.

As an example, let's say you have a weblog of restaurant reviews. You want to store custom data about each restaurant such as its location, cuisine, average meal price, and a numeric rating. Your table definition statement would look something like this:

CREATE TABLE mt_restaurant (
    restaurant_id INTEGER NOT NULL,
    restaurant_location VARCHAR(100),
    restaurant_cuisine VARCHAR(40),
    restaurant_price VARCHAR(20),
    restaurant_rating TINYINT,
    INDEX(restaurant_id)
);

Once you've figured out your table definition, log in to your MySQL database and create the table.

3) Entering Configuration Information

ExtraFields associates the external tables with weblogs by means of a configuration file, EFConfig.txt, which resides in your extlib directory. The format for the custom field setup for a given weblog is as follows:

blog_id:datasource
colname1:Column Label 1:lines
colname2:Column Label 2:lines

To find the blog_id of a particular weblog, log in to Movable Type and click on any link related to that weblog (New Entry, Manage Blog, etc.). The URL for the link will contain the ID you're looking for, as in &blog_id=7.

The datasource is the name you chose in section 2, above—the table name, but without the mt_ prefix.

Each colname is the name of the column as defined in your table, but without the datasource_ prefix. Note that you do not include the id column in this listing.

Each Column Label is a descriptive label for the field. This label will appear on the entry editing screen in MT, and can also be displayed on a template by using the ExtraFields plugin tags.

The lines value denotes how large you want the editing area for this field to be. If lines is 1, a type="text" input element will be displayed. If lines is greater than 1, a textarea element with the specified number of lines will be displayed.

Let's return to the restaurant example. If the weblog in which you're writing restaurant reviews had a blog_id of 7, your config file would look something like this:

7:restaurant
location:Location:1
cuisine:Type of Cuisine:1
price:Average Meal Price:1
rating:My Rating:1

Multiple weblogs are delimited by a line with five hyphens (-----).

If you wanted to, you could have a single external table corresponding to different custom fields for more than one weblog. You might set up a generic table like this:

CREATE TABLE mt_extra (
    extra_id INTEGER NOT NULL,
    extra_col1 VARCHAR(255),
    extra_col2 VARCHAR(255),
    extra_col3 VARCHAR(255),
    extra_col4 VARCHAR(255),
    extra_col5 VARCHAR(255),
    INDEX(extra_id)
);

Then in your config file, you would simply enter different labels for different weblogs. Let's say you want to store book reviews in one weblog (ID=3) and movie reviews in another (ID=6):

3:extra
col1:Amazon URL:1
col2:Author:1
col3:Publisher:1
col4:Year:1
col5:Pages:1
-----
6:extra
col1:IMDb URL:1
col2:Director:1
col3:Releasing Company:1
col4:Year:1
col5:Length:1

4) Modifying CMS.pm

Now that you've defined your custom fields, you need to add some code to a couple of MT files to get the fields to show up on the entry editing screen.

First, you'll make some changes to a Perl module in the lib directory within your MT directory. The file you need to edit is lib/MT/App/CMS.pm. Make a backup copy first in case anything goes wrong and you need to revert to the original version.

There are six additions that need to be made to this file. If you're on a Unix system and you know how to do such things, you can simply apply the patch included in the ExtraFields package. Two versions of the patch are provided. If you're using 2.661, apply ef_diff26.txt. If you're using 3.16, apply ef_diff3.txt.

If you don't know how to do this or prefer to make the changes manually, edit the CMS.pm file according to the following steps (they're in reverse order relative to where they go in the file, so that each change doesn't throw off the line numbers of the subsequent ones):

  • Find this line of code, which is line 3430 in the original file (line 2169 in MT 2.661):
        my $cols = MT::Entry->column_names;
    After that line, insert this line:
        push(@$cols, ef_column_names($blog_id));
  • Find this line of code, which is line 2841 in the original file (line 1734 in MT 2.661):
        ## If the saved status is RELEASE, or if the *previous* status was
    Before that line, insert this line:
        ef_save($obj->blog_id, $obj->id, $q);
  • Find this line of code, which is line 1833 in the original file (line 1260 in MT 2.661):
                $obj->remove;
    After that line, insert this line:
                ef_delete($q->param('blog_id'), $id) if ($type eq 'entry');
  • Find these lines of code, which are lines 1031-1032 in the original file (lines 729-730 in MT 2.661):
                    $param{disp_prefs_bar_colspan} = $param{new_object} ? 1 : 2;
                }
    After those lines, insert this line:
                ef_prepare_html($blog_id, \%param);
  • Find these lines of code, which are lines 693-694 in the original file (lines 499-500 in MT 2.661):
                        $param{previous_entry_id} = $prev->id;
                    }
    After those lines, insert this line:
                    ef_load($blog_id, $id);
  • Find this line of code, which is line 17 in the original file (line 14 in MT 2.661):
    @MT::App::CMS::ISA = qw( MT::App );
    After that line, insert this line:
    use ExtraFields;

OK, that should do it.

5) Modifying edit_entry.tmpl

This one is much simpler. You're going to make just one addition to one of the page templates used by the Movable Type CMS, which is in the directory tmpl within your MT directory. The file you need to edit is tmpl/cms/edit_entry.tmpl. Make a backup copy first in case anything goes wrong and you need to revert to the original version.

For MT 3.16: Find the following lines of code, which are lines 240-242 in the original file:

</div>

<TMPL_IF NAME=DISP_PREFS_BASIC>

Before those lines, add this line:

<TMPL_VAR NAME=EF_FIELDS>

For MT 2.661: Find the following lines of code, which are lines 427-430 in the original file:

		</tr>
		</TMPL_IF>

		</table>

Between the </TMPL_IF> line and the </table> line, add this line:

		<TMPL_VAR NAME=EF_FIELDS>

6) Trying It Out

Once you've followed the steps above, you should be ready to start entering data in your custom fields. To verify that everything's working properly, try the following test:

  • Log in to MT.
  • Create a new entry in the weblog for which you've just defined custom fields.
  • Look at the entry form. In addition to the standard MT fields, you should see the custom fields you just defined for this weblog.
  • Enter some text in each of the custom fields.
  • Save the entry.

When the entry form reloads after the entry is saved, confirm that the text you just entered appears again in the custom fields. If so, ExtraFields is now up and running, and you can start including your custom data in your entries. Now all that remains is to get this data to appear on your pages, which you can do by using the ExtraFields plugin tags.

7) Troubleshooting

If you have trouble getting ExtraFields to work, you can try installing the EFDebug.pl plugin. This file contains a tag that will try to load the ExtraFields module, load the configuration file, and create and delete a sample row for each weblog. It will display the results of this testing, which may be useful in figuring out why ExtraFields isn't working. Just put this tag on a template (probably not one you're actually displaying to users) and rebuild the template:

<$MTExtraFieldsDebug$>

PLUGIN TAGS

To display the custom data for an entry, place these tags in your template. Like other tags that display entry data, they must be used within an MTEntries container tag.

The following example shows how you might display the custom fields defined in the restaurants example in the Installation section:

<MTEntries>
 <p><$MTEntryTitle$><br>
 <$MTEntryBody$>
 <MTExtraFields>
  <MTIfExtraFields>
   <p>ADDITIONAL INFORMATION:<br>
   <MTIfExtraField field="location">
    Location: <$MTExtraFieldValue field="location"><br>
   </MTIfExtraField>
   <MTIfExtraField field="cuisine">
    Type of Cuisine: <$MTExtraFieldValue field="cuisine"><br>
   </MTIfExtraField>
   <MTIfExtraField field="price">
    Average Meal Price: <$MTExtraFieldValue field="price"><br>
   </MTIfExtraField>
   <MTIfExtraField field="rating">
    My Rating: <$MTExtraFieldValue field="rating"> of 4 stars<br>
   </MTIfExtraField>
  </MTIfExtraFields>
 </MTExtraFields>
</MTEntries>

MTExtraFields

This container tag loads the custom field data for the current entry. All the other ExtraFields tags must be contained within this tag.

MTIfExtraFields

This container tag displays its contents if two conditions are met: A) you've defined custom fields for this weblog in your configuration file, and B) there is data entered in at least one of the custom fields for the current entry. Otherwise, it displays nothing.

MTIfExtraField

This container tag prints its contents if there is data entered in the specified custom field for the current entry.

The tag takes the following attribute:

  • field="fieldname" (required, unless looping)
    The name of the custom field to be checked for data. You can either include or omit the datasource_ column name prefix.

MTExtraFieldValue

This tag displays the value of the specified custom field—that is, it displays whatever data you've entered into the field for the current entry.

The tag takes the following attribute:

  • field="fieldname" (required, unless looping)
    The name of the custom field whose will should be displayed. You can either include or omit the datasource_ column name prefix.

MTExtraFieldLabel

This tag displays the label for the specified field, as defined in your configuration file.

The tag takes the following attribute:

  • field="fieldname" (required, unless looping)
    The name of the custom field whose label will be displayed. You can either include or omit the datasource_ column name prefix.

MTExtraFieldsLoop

This container tag loops through all the custom fields that have been defined for this weblog, printing its contents once for each field. The fields will be looped through in the order in which they're defined in the configuration file. Within the loop, MTIfExtraField, MTExtraFieldValue, and MTExtraFieldLabel refer to the field in the current loop iteration.

The following example will display the custom data for the restaurant example, but without having to call in the fields individually in the template:

<MTEntries>
 <p><$MTEntryTitle$><br>
 <$MTEntryBody$>
 <MTExtraFields>
  <MTIfExtraFields>
   <MTExtraFieldsLoop>
    <p>ADDITIONAL INFORMATION:<br>
    <MTIfExtraField>
     <$MTExtraFieldLabel$>: <$MTExtraFieldValue$><br>
    </MTIfExtraField>
   </MTExtraFieldsLoop>
  </MTIfExtraFields>
 </MTExtraFields>
</MTEntries>

VERSION HISTORY

4/20/05 - updated documentation and diff file for MT 3.16

1/12/05 - updated documentation and diff file for MT 3.14

9/21/04 - updated documentation and diff file for MT 3.11

8/23/04 - updated documentation and diff file for MT 3.01D

7/7/04 - version 0.6

  • Updated form field HTML for entry edit screen to use CSS formatting in MT 3.
  • Plugin now registers itself with MT 3 interface.
  • Updated documentation for MT 3.
  • Added package declaration and $VERSION variable.
  • Conditional container tags are now declared as conditional tags, so they should work with MTElse.

3/9/04 - version 0.51

  • All container tags now pass conditions along when building contents, so they'll work outside conditional tags within MTEntries, etc. (mirra)
    NOTE: In order to install this update, all you need to do is replace the ExtraFields.pl file.

5/6/03 - added EFDebug.pl troubleshooting plugin and updated documentation

2/18/03 - updated documentation and diff files for MT 2.6

11/5/02 - version 0.5 released


The End As I Know It: A Novel of Millennial Anxiety, by staggernation.com proprietor Kevin Shay, is now available in paperback.

Please visit kshay.com for more information.