Monthly Archives: November 2010

Extending Anthologize: Part 2

In my last post, I gave a brief overview of what happens when you click the Export Project button in Anthologize, with an eye toward demonstrating the role that third party plugins (written by people Just Like You!) can play in extending the software. In this post, I’ll flesh out some of those details.

Step 1: Anthologize, meet my format

Anthologize has what I like to think of as two internal APIs: the WordPress-facing API, and the theming API. The first step is to let Anthologize know that your format exists, which you’ll do by using the key function in the WP-facing API: anthologize_register_format(). (Check out how the WPAPI functions work in the source.) You should call anthologize_register_format() in a function hooked to anthologize_init, which ensures that it won’t fire before Anthologize is ready for it. Here’s a simple example:

function register_my_anthologize_format() {
	$name = 'example_format';
	$label = 'My Anthologize Format';
	$loader_file = dirname(__FILE__) . '/base.php';

anthologize_register_format( $name, $label, $loader_file );
}
add_action( 'anthologize_init', 'register_my_anthologize_format' );

anthologize_register_format_option() takes three arguments. The first is the name that Anthologize will use internally as a unique key for your format. The second is the name that users will see on the Export screen radio button and elsewhere in the interface. (It’s a good idea to set a textdomain for your strings so that they can be translated – eg $label = __( 'My Anthologize Format', 'my-anthologize-plugin' );.) The third argument is the absolute server path of your main translator file, the file that will be loaded at export time.

You can read a more in-depth example, embedded in a loader class, in this bare-bones plugin that I built for testing purposes. And the definitive examples, of course, can be found in the way that Anthologize registers its native export formats (yum, we love eating our own dog food!).

What does this give you? First, it makes your format available as a format option on the second screen of the export process:



Second, it gives your format a Publishing Options page. Since we haven’t registered any options yet, we get the bare minimum, the shortcode toggle that all formats get:



Third – and this is the big thing – anthologize_register_format() tells Anthologize that, if the user has selected your format on the export screens, the TEI document containing the project data will be handed off to the translator file whose path you specified when you registered the format. That’s where the format translation itself happens.

Step 2: Gimme some options

One of the big thoughts behind the Anthologize plugin architecture is to model WordPress’s design philosophy, which is to provide relatively few options in the core product but to allow for arbitrarily extended functionality by plugins. That’s the purpose behind anthologize_register_format_option(), the second pillar of Anthologize’s WP-facing API. anthologize_register_format_option() gives a framework for plugins to register any kind of option associated with their custom format, provides all the integrated markup for presenting those options to users, and passes along the user’s choices to the Anthologize TEI document used for format translation.

Format options can also be loaded at anthologize_init, though you should be careful to load them after the format itself. I’ll do that by using an add_action priority:

function register_my_anthologize_format_options() {
	$website_name = 'website';
	$website_label = 'Website';
	$website_type = 'textbox';

anthologize_register_format_option( 'example_format', $website_name, $website_label, $website_type );	
}
add_action( 'anthologize_init', 'register_my_anthologize_format_options', 15 );

(Note that the first argument is the unique $name of the format I intend to associate the option with.) This registers a plain textbox with the label ‘Website':



You can also register checkboxes, if you need a Boolean:

$option_name = 'include_dedication';
$option_label = 'Include Dedication?';
$option_type = 'checkbox';

anthologize_register_format_option( 'example_format', $option_name, $option_label, $option_type );	


Or you can register dropdowns:

$fontface_format_name = 'example_format';
$fontface_option_name = 'font-face';
$fontface_label = 'Font Face';
$fontface_type = 'dropdown';
$fontface_values = array(
	'courier' => 'Courier',
	'georgia' => 'Georgia',
	'garamond' => 'Garamond'
);
$fontface_default = 'georgia';

anthologize_register_format_option( $fontface_format_name, $fontface_option_name, $fontface_label, $fontface_type, $fontface_values, $fontface_default );

This kind of option highlights some of the other possible arguments that anthologize_register_format_option() will take: an array of possible values, and a default selected value:


All the options you provide, and in particular the options selected by the user at export time, are handed to your main translator file at the very end of the Anthologize export process.

So that’s how you get your format and its options registered on the WordPress side of things. Stay tuned for a discussion of how translators might be built.

Are you a potential plugin developer with ideas about how this API might evolve to better suit your purposes? Hop onto the dev list.

Extending Anthologize: Part 1

Anthologize has seen two version releases since its initial launch in August. Much of the progress since then (aside from some smallish – but needed – features and bugfixes) has been centered on the development of a plugin architecture for Anthologize, a system that will allow individuals to build custom output formats for their Anthologize content in a relatively straightforward way. Anthologize development team member (and metadata badass) Patrick Murray-John has been hard at work on this project: creating prototype plugins, writing blog posts about the plugin process, and of course building large parts of API itself. In this series of posts, I’d like to augment some of Patrick’s specific musings with a general explanation of how Anthologize works, and how the plugin API lets you tap into it. Think of it as an introduction to Anthologize plugin building.

First, a brief peek under the hood. Anthologize’s tagline is “Use the power of WordPress to transform online content into an electronic book.” How does Anthologize take you from point A – your WordPress content – to point B – your ebook? When you press the Export button on the final Export Project screen, you set into motion a two-step process.

Step 1: WordPress to TEI(ish)

WordPress content is stored in the wp_posts database table, and is typically accessed using WP’s “loop”, which is a set of iterative and indexical functions that make it easy to get and display post data in whichever way you’d like. When you hit the final Export button, Anthologize catches the form submit and hands things off to the format translator, which will get the content out of the database. We’ll use PDF as our example. The main translator file is base.php. That file acts like a top-level manager for all the things that have to be done in order for PDFs to be generated. The first important thing that any export format has to do is to call up the content of the project, which it does by instantiating the TeiDom class.

In many ways, TeiDom is the workhorse of Anthologize. Using the session data passed to it from the PDF base.php file – data that includes the project id, the desired page size, the content of the dedication, stuff like that – it uses a variation on The Loop to collect each part and item from an Anthologize project. Those objects, along with their metadata, are then fed into an empty TEI template file before getting handed back to the individual export format translator.

Why the middleman? Early in the development process, the team made a few decisions about the way that Anthologize ought to operate. First, though it’s currently being developed as a WordPress plugin, we should anticipate a time when much of Anthologize could be ported to another CMS or to a standalone application. If format translators like PDF had to dig directly into the WP database, or were forced to use The Loop to get project data, then they’d have to be refactored when the data lived somewhere other that WP. TEI is a platform-independent format, and since format translators like the PDF generator communicate only with the TeiDom (not directly with WordPress), they should be fairly platform-independent as well. Second, if we were going to have a middleman, we wanted it to be one with extremely broad expressive power, and one for which standards and translation techniques already exist. By choosing TEI, we open the door for armies of archivists, librarians, and other such format wizards, armed with XSLT ninjitsu. (In fact, that’s how Anthologize dev team member Patrick Rashleigh built the Anthologize epub generator!)

In the header for this section, I say TEI(ish) rather than TEI. That’s because the Anthologize middleman TEI layer is not the kind of TEI that your local text-encoder might expect. In particular, the content of your WordPress blog posts, which is already marked up with HTML, is untouched in the export process. A true TEI markup of your text would mean lots of manual encoding, so we just pass it along as-is. This untouched HTML post content, however, is embedded in a larger TEI framework for holding the metadata and generally explaining the structure of the project document. It’s not necessarily the kind of document you could use to build a richly marked-up text visualization, but it works well for the purposes of simple presentation.

Step 2: TEI to your format

Once the format generator (remember our friend templates/pdf/base.php?) gets the TEI document back from the TeiDom workhorse – which is essentially shared by all Anthologize export formats – the format-specific work can begin. PDF uses its own custom TEI-to-PDF class, along with an included PDF generation library, to parse the TeiDom object and turn it into something that, when delivered to your browser, is understood as a PDF. This, of course, is the hard part of building a translator, and is very format-specific.

The cool part about this part of the process, though, is the amount of flexibility that is emerging from the Anthologize architecture. Different format translators can deal with data in different ways; to wit:

  • The built-in PDF generator uses XPaths and some basic PHP loopage to format the final document. It’s also got some custom helper methods (eg get_book_title()) that it uses to make the the rendering code a bit easier to use.
  • The built-in ePub generator uses XSL transformations to move from the TEI document to the HTML-esque ePub output.
  • Patrick MJ has been working on a set of theming functions that will allow plugin authors to construct a loop very similar to the WordPress post Loop for the display of their data.
  • Because of the nature of PHP applications, export formats could always bypass Anthologize’s TEI and other API options and head directly for the WP database, using some embedded WP_Query/have_posts() loops.

Once your parser has turned Anthologize TEI data into the format necessary for your chosen format, you’ll need to deliver it to the browser by sending the write headers (here’s how ePub does it as an example).

In my next blog post, I’ll use an example to show how a plugin can register itself with Anthologize to take advantage of all these goodies.

New BuddyPress plugin: BP Group Reviews

I’m working on a project that needs to allow users to leave reviews of groups, kinda like buddypress.org does with plugins. So, with Andy’s permission, I cleaned up, packaged, and extended his code into a new plugin, BP Group Reviews. It allows users to leave a star rating and a text review of any group on your BuddyPress installation.