Introduction

MTTacFeed (MTTF) is a plugin to create feeds from the comments and trackbacks of a Movable Type weblog. “TacFeed” can be read as “Trackbacks and Comment Feed” or “Tactical Feed”, which isn’t as mnemnonic but sounds cooler.

The fundamental operation of TacFeed is to first select a set of objects, then order those objects for display. The objects are usually comments, but can also be trackback pingss and entries. The ability to order the objects is the real meat of TacFeed. A variety of different properties are available for sorting, the objects can be sorted on an arbitrary set of properties, and the display code can check for differences in properties between adjacent objects to generate headers and footers.

Excited? Well, read on anyway.

Note: This plugin is currently under development and not ready for deployment to weblogs that I don’t administer.

Usage

The primary tag for MTTacFeed is the MTTacFeed tag1. This is a container tag that selects, orders, then iterates over the objects. It is vitally important to keep in mind that selecting and ordering two operations are distinct — once an object is selected, it will be iterated over by the container. The selection doesn’t care what order is later put on the objects, and the ordering doesn’t care how the objects were selected.

All other tags for this plugin are used during the iteration, inside the MTTacFeed tag.

MTTacFeed

The purpose of MTTacFeed is to select feedback objects, comments or trackback pings. The container tag has attributes to control this selection. Related to the feedback objects selected is the set of entries to which those objects are associated. This is termed the entry selection set because we’ll be talking about it quite a bit.

Generalities

The entry selection set can be implicit, explicit, or both. Feedback objects can be selected based on their own properties (making the entry selection set implicit) or based on properties of the entries (making the entry selection set explicit), or both (making the situation confusing).

After selecting the objects, the objects are ordered. Doing this requires two concepts, metrics and axes. A metric is a way of measuring a property. Ultimately, all ordering in MTTacFeed depends on being able to order the values of a property2 and uses the term “metric” to describe this. A specific instance of using a metric to order the objects is called an axis. The ordering of the objects is done by a set of axes, each of which has an associated metric.

This is analogous to drawing graphs. For example, one might have “number of readers” and “dollars per year” as metrics. One could then use those to create a graph of various weblogs by putting using “number of readers” along one axis and “dollars per year” along another axis. While the metrics are clearly related to the axes, they are not the same thing and it’s important to keep them distinct.

MTTacFeed metrics are always discrete, not continuous. Because of this, it will usually be the case that multiple objects will have the same value for a metric. In that case, MTTacFeed will consider them equivalent for that metric and will put them in an arbitrary (undefined) order along an axis using that metric. Rather than being a problem, MTTacFeed depends on this feature and is designed to take advantage of it.

Axes in MTTacFeed are always nested. There is an outermost axis, inside of which is an inner axis, inside of that a more inner axis, etc. to any desired depth. The outermost axis groups the objects by its metric. Each of those groups is then internally ordered by the next inner axis. This process continues, each grouping being sub-grouped by the next inner axis to the innermost axis. It is this which gives MTTacFeed its power and it wouldn’t work if the outermost axis completely determined the order of the objects.

The last concept needed is that of an edge, which is the change in value of a metric from one object to another. These are the same thing as group boundaries along an axis, but “edge” is shorter to type. MTTacFeed also distinguishes between a trailing edge and a leading edge. The former is change between the current object in the iteration and the previous object, while the latter is a change between the current object and the next object. Note that one object’s leading edge is the next object’s trailing edge. The use of the term “edge” means a change without reference to a particular object. However, in actual use any template code will be processed with regard to a specific object during the iteration, so that in practice the template code must deal with leading and trailing edges.

Illustation

With the generalities as a background we will consider an example. This is just to illustrate the generalities, which can be difficult for non-math geeks to graph. A more extensive set of examples is provided elsewhere.

Suppose we wanted to display the set of recent comments on a weblog. We don’t want just a flat list3. What we would like is to have a section for each day, then under that a title for each entry that was commented on that day, with the comments grouped under that oldest to newest. In MTTacFeed terms, that would be three axes, using the metrics “day”, “entry ID”, and “comment ID”. MTTacFeed would order by day, putting the comments for each day in an arbitrary order. Each day would then be ordered by the entry, and for each entry by the comment ID. The ability to detect edges lets us put the desired titles in. We can put in a day label for every edge in the “day” axis, and an entry title for each edge in the “entry ID” axis.

The purpose of MTTacFeed is to create this kind of ordering easily so that feeds can be customized for various purposes without having to write Perl code to do it for each feed.

Time

Time isn’t a new concept, but MTTacFeed handles it in a slightly different way.

The most important point is that MTTacFeed has two types of time, “absolute time” and “span time”. Absolute time could also be called “calendar” time. The difference between these two is where the edges are. Absolute time edges are always aligned with the calendar or clock. E.g., the “day” metric from the previous example would have edges at the same points in time as a calendar as an absolute time. Span time, in contrast, has its edges based on the current time, each edge a particular span of time before then without regard to anything else. E.g., “this day” is the same calendar day for absolute time, and within 24 hours of the current time for span time. Both of these are useful and so both are supported.

MTTacFeed accepts time specifications in two formats. The first is the standard Movable Type timestamp, 14 digits of the form YYYYMMDDHHMMSS. Such a specification is always absolute time. The other form, a timespec, is a sequence of digits and letters, the letters selected from this case sensitive list —

LetterTime Period
sSecond
mMinute
hHour
DDay
WWeek
MMonth
YYear

The leading digits are treated a number specifying the number of time units indicated by the letter. The digits can have a leading dash to indicate a negative number. For example, “1Y” means “one year”. “1W1D” means “a week and a day”, which is the same as “8D”. 90 minutes can be “1h30m” or “90m” or “2h-30m” or “5400s”. Span time is always specified as a timespec, but a timesec can be used in other situations. Unless otherwise noted, any place a “time” is needed can be specified as either a timestamp or a timespec.

Attributes

The MTTacFeed tag has the following attributes:

after
Specifies the earliest time for a selected object — only select objects after this time. If omitted it is taken to be earlier than the earliest object.
axes
Specifies the set of axes for iteration. More detail
base_entries
Specify the entry selection set. Regardless of any other attribute, only feedback objects with associated entries that are members of the set of entries specified by this attribute will be seleted. More detail
before
Specifies the latest time for a selected object — only select objects before this time. If omitted it is taken to be later than the current time.
count
The maximum number of objects to select. This attribute does not select any objects but simply puts an upper bound on the number of objects selected by other attributes. There is no guarantee that this many objects will be selected. If exactly one of after or before is specified, then objects are discarded from opposite direction. Otherwise, the earlier objectts are discarded.
include_entries
Specifies entries to include in the set of objects. This has no effect on which feedback objects are selected. More detail
type
Specifies the types of objects to automatically select. If the value contains the letter “t” or “p” then trackback pings are selected. If the value contains the letter “c” then comments are seleted. Entries are included only if specifically requested via the include_entries attribute and so are not specified here.

count is generically useful, particularly to limit the size of the output. offset is useful in conjuction with paging and other techniques that require successive chunks of comments. after and before allow specific time ranges to be selected.

Axis Definition

Each axis in the axes attribute is separated by a semi-colon and is of the form

metric [ ( parameter-list ) ] [ = name ]

The option list and name are optional, as indicated by the []s. If there are multiple parameters, they must be separated by commas. Any leading or trailing white space is stripped and then numeric entities are converted to the characters they represent before processing. This can be used to include commas, leading spaces, or quotes in the parameters.

id
Internal object numeric identifier.
entry
The internal numeric identifier of the associated entry.
span
A time span. This has a required timespec parameter, which specifies the length of the time span. The current time is always a boundary, with other boundaries at multiples of the specified interval away.
time
Absolute time. This has a required timespec parameter. The boundaries are set at the natural boundaries for the timespec as close to the current time as possible.
author
The author of the object.

All metrics take an optional parameter of ‘reverse’, which reverses the ordering.

Each axis can be named so that it can be referenced by other MTTacFeed tags. If not specified, the axis is named the same as its metric. Names must be single alphanumeric words, no spaces or punctuation permitted4.

Entry Specifiers

The base_entries and include_entries specifiers require the selection of a set of entries. Both of these tags take (almost) the same set of specifiers, which are very similar to the metric specifiers used for axis definitions. The available specifiers are

author
The parameters are weblog author names. Entries with that name are selected.
lastn
The n more recent entries, where n is a number supplied as a parameter.
after
Entries after a specific time. The time is passed in as a parameter.
before
Entries before a specific time. The time is passed in as a parameter.
commented_on_by
The parameters are a list of names. The selected entries are those that have a comment by one of the names.

Iteration

After all of the object selection and ordering has been done, the MTTacFeed tag iterates over the objects in order. For each iteration the contents of the container are evaluated and added to the final output.

During an iteration, the container sets up the appropriate MT context for the object. In addition, the associated entry and weblog for the object is placed in the context so that entry and weblog based tags are available in addition to the comment or trackback (as appropriate) tags.

Other Tags

In addition to the top level container class, MTCatFood also provides conditional tags for controlling presentation. These are the MTTacFeedFIfHeader, MTTacFeedIfFooter, and MTTacFeedIfEdge tags.

MTTacFeedIfHeader and MTTacFeedIfFooter are true if a specified axis or any outer one has an edge. MTTacFeedIfHeader checks for trailing edges, i.e. that the current object has a different metric value than the previous object. MTTacFeedIfFooter checks for a leading edge, i.e. that the current object has a different metric value from the next object. The base axis to check is specified by the axis attribute, which can be either the 0-based numeric index of the axis, or the name.

To go back to the previous example, the MTTacFeed container attribute axes would be “span(1D);entry;id”. To put a header for each day, we would use

<MTTacFeedIfHeader axis="span"><h1><MTCommentDate></h1></MTTacFeedIfHeader>

because the current object determines the MT context and in this case it is always a comment. The container will also set up the associated entry of the comment in the context, so the entry header can be done using

<MTTacFeedIfHeader axis="entry"><h2><MTEntryTitle></h2></MTTacFeedIfHeader>

In this case the cascading edge check insures that a new entry header will be present at the start of each day, even if the associated entry is the same as the previous comment.

The MTTacFeedIfEdge tag is more esoteric and shouldn’t be necessary for most uses. It provides the ability to trigger on any edge boundary on any set of axes. It takes two attributes, header and footer. Each of these is a sequence of axis specifiers (0-based index or name) separated by commas or spaces. The condition is true if any of the specified axes have a trailing or leading edge respectively. Only explicitly names axes are checked, there is no cascading check.

While the set of objects for iteration is by default only comments, it is possible to include trackback pings and entries. To handle these situations, MTTacFeed provides the MTTacFeedIfComment, MTTacFeedIfPing, and MTTacFeedIfEntry tags which are true if the current object is of the appropriate type.


1 The only simple and obvious thing in the entire plugin, so enjoy it while you can.

2 Duh! It’s ordering.

3 Or we wouldn’t be reading this documentation, would we?

4 Really, just how complex do you really need to make the names of the axes?