Here are some notes, thoughts, and ramblings of interest to those looking to become involved with Litmus development. Feel free to add to this page and post questions or clarifications.
Litmus is more or less organized as a classic MVC (Model View Controller) application. Two perl modules are used to facilitate this, Class::DBI and the Template Toolkit, and it's a good idea to have some familiarity with these modules when working on Litmus.
The Model - Class::DBI
Since writing SQL by hand is a pain, Litmus uses Class::DBI to talk to the database. The schema is contained in a set of perl modules found in litmus/Litmus/DB, and the cgi scripts and templates interact with the database using these modules. When it is necessary to write more complex database queries (or where queries have been tuned manually and in-lined for performance reasons), Class::DBI provides several methods to allow for manual SQL queries. Additional subroutines in the Litmus::DB::* modules handle these needs. It's worth taking a quick look through the Class::DBI documentation, or looking at some of the Litmus code that uses it, for a quick overview.
The View - Template Toolkit
Litmus uses the Template Toolkit to generate its output. Templates are conveniently stored in the templates/ directory (please use caution when opening the directory, as contents may have shifted during the flight). Currently, all templates are the default templates and are written in English, but since Litmus may one day want to support localizations and customizations, the template files themselves can be found in templates/en/default. The overall configuration for the template system is located in litmus/Litmus/Template.pm.
Once a CGI script has done whatever retrieval or processing it needs to do, it prepares a collection of one or more variables to be sent to the template. Each template defines an interface (described in a comment at the top of the template file), indicating what variables it requires and what variables are optional (there is currently no error checking here, so things may blow up if you don't pass all required variables to a template). The script then calls Template->process(), passing it the name of the template file and the variable list. The template can then access and manipulate these variables.
The template language itself is fairly straightforward. Everything that's not a template tag is just straight HTML and gets sent to the browser. Template tags are indicated with the markers
%]. Commands are fairly normal (IF, FOREACH, etc...), but see the Template Toolkit documentation or the existing templates for more details. To use a variable, just give its name. Methods can be invoked with the dot (.) operator. For example, if the variable named "test" contains a Litmus::DB::Test object and you want to print its testid, you can just say
[% test.testid %].
One important note: to prevent cross-site scripting attacks, it's important that any information coming from the database be "filtered," such that any HTML tags are properly escaped. To do this, just use the FILTER command when mentioning a template variable. In other words, the example above should really be written as
[% test.testid FILTER html %]. Other filters exist for more specialized situations, such as "js" and "testdata" (which allows only a specific list of html tags that are allowed to appear in testcases). When in doubt, filter it.
- Class::DBI doesn't allow you much flexibility with your SQL, making it hard to improve DB performance by simply tweaking queries. In Litmus, we've resorted to sub-classing and have some custom SQL outside of the Class::DBI object framework. Maintaining these two approaches in one application is not ideal.
- Class::DBI doesn't handle pure join tables very well (see above).
- templates are cached, but much of the information to fill pages is looked up on-the-fly with little/no caching. See bug 419688 for more information.
Where to find stuff
Most of the files in the Litmus codebase are fairly self-explanatory. Here's a short guide to where things are kept.
- schema.pl - the database schema. Used at install-time to create the Litmus tablespace.
- populatedb.pl - creates the initial configuration of products, groups, etc... Currently the only way to manipulate these features.
- localconfig - installation-specific configuration, including database name and authentication details.
- Litmus/ - libraries and modules.
- Litmus/DB - Class::DBI modules for each database table. The M in MVC.
- css/ - core styles
- skins/ - skin-specific css files, images, etc...
- templates/ - template files. See above for details.