MidCOM 3 at a glance

This document has been written as a quick Midgardized version of the nice “Django at a glance” tutorial, in order to explain how the new and upcoming MidCOM 3 framework works. In addition publishing this as a blog post, this document will be maintained in the MidCOM 3 version control tree.

MidCOM 3 has been designed to be an extensible and highly configurable CMS development environment. It provides several basic building blocks like toolbars, access controls and management of static content pages out-of-the-box.

MidCOM applications are built as “components” with Java-like namespacing. This means that a “news” component designed by company named Nemein could be called net_nemein_news. Components are run on a Midgard site by setting a folder of the site to use that component.

Design your model

MidCOM uses Midgard’s MgdSchema object-relational mapping system for providing easy object-oriented API for database storage. Models are described using XML syntax, and Midgard then provides OOP APIs to them for C, PHP and Python languages.

Here is a simple example MdgSchema:

<?xml version="1.0" encoding="UTF-8"?>
<Schema xmlns="http://www.midgard-project.org/repligard/1.4">
  <type name="net_nemein_news_article" table="net_nemein_news_article">
    <property name="id" type="integer" primaryfield="id" />
    <property name="name" type="string"/> 
    <property name="title" type="string" multilang="yes" table="net_nemein_news_article_i" />
    <property name="content" type="longtext" multilang="yes" table="net_nemein_news_article_i" />

Other fields like author or publication date do not need to be defined in the MgdSchema as Midgard automatically extends all records with a set of metadata properties.

Install it

Place the MgdSchema XML file to /usr/share/midgard/schema, and then create the database tables based on it by running:

$ midgard-schema midgard

Where midgard is the name of your Midgard conf.d file that defines the database access parameters like database type and password.

Enjoy the free API

These steps are all you need to do to have new Midgard objects at your disposal. Now you can access and manipulate them using for example Python or PHP. With PHP, the API looks like this:

// Create a new person
$reporter = new midgard_person();
$reporter->firstname = 'John';
$reporter->lastname = 'Smith';

// Save it to the database

// Now it has an UUID
echo $reporter->guid;

// And it can be fetched from the database
$qb = midgard_person::new_query_builder();
// This would print an array of midgard_person objects containing "John Smith"

// We have multiple ways to query objects
$qb->add_constraint('lastname', 'LIKE', 'Smi%');

// Create a new article
$article = new net_nemein_news_article();
$article->title = 'MidCOM is cool';
$article->metadata->authors = $reporter->guid;

// Extend the article with new properties
$article->parameter('namespace', 'key', 'value');

// Localize the article to Finnish
$article->title = 'MidCOM on ältsin magee';

// Delete the Finnish translation

/// etc

A dynamic admin interface

Midgard comes with Asgard, an automated administrative interface which provides a full editing tool to all our installed MgdSchemas. If your define a tree model for your storage, it will even provide a nice navigation tree for them. For example:

<?xml version="1.0" encoding="UTF-8"?>
<Schema xmlns="http://www.midgard-project.org/repligard/1.4">
  <type name="net_nemein_news_article" table="net_nemein_news_article" parent="midgard_topic">
    <property name="id" type="integer" primaryfield="id" />    
    <property name="name" type="string"/>
    <property name="title" type="string" multilang="yes" table="net_nemein_news_article_i" />
    <property name="content" type="longtext" multilang="yes" table="net_nemein_news_article_i" />
    <property name="topic" type="integer" link="midgard_topic:id" parentfield="topic"/>

After this the net_nemein_news_article objects would be stored under topics, and could be browsed in the topic tree hierarchy.

Asgard understands linked properties, datetime fields, and other MgdSchema field types and provides appropriate editing tools for them. For example, linked fields automatically become search-based choosers.

At this point you can already start entering content to your new application using the Asgard tool.

Design your URLs

A clean URL space is important in a modern web framework, and with Midgard clean URLs have been the norm even since the 90s.

In MidCOM your application URL space is set up as something called “routes”. They are entered in YAML format to the component’s configuration file, in this case net_nemein_news/configuration/defaults.yml. The routes follow the IETF URI template draft format.

For example, a route for displaying a particular article could be defined as:

    controller: net_nemein_news_controllers_article
    action: show
    route: /{$name}/
    content_entry_point: nnn-show-article

In this case, the URL to a news article would be /foldername/articlename.

The routes define many things about what MidCOM should do with the request. First of all, they define which controller PHP class, and which action method in it will deal with the request. Additionally the route can define a template_entry_point or content_entry_point to choose which template files will be used for displaying the page. Other things like templating language and MIME type can also be defined in the configuration file.

Routes are stored in configuration file so that they can be easily overridden on per-site, or even per-folder basis. This means that migration from some other CMS system is quite easy as the site can be configured to retain the old URL formats.

Write your controllers

Each controller is responsible for doing one of two things: Populating a data array with content of the requested page, or raising an exception like midcom_exception_notfound.

The controller class in this case would be stored to net_nemein_news/controllers/article.php and could look like the following:

public function action_show($route_id, &$data, $args)
    $qb = net_nemein_news_article::new_query_builder();
    $qb->add_constraint('name', '=', $args['name']);        
    $articles = $qb->execute();        
    if (count($articles) == 0)
        throw new midcom_exception_notfound("Article {$args['name']} not found.");
    $data['article'] = $articles[0];

After the controller has produced the data it will then be passed to the MidCOM templating system according to the entry points defined for the route.

Design your templates

MidCOM uses the Template Abstraction Language (TAL) for its templating purposes. TAL is a very powerful templating system in the sense that it allows designers to build the site XML or XHTML templates and fill them with example data that will then be replaced with the real data when TAL is run.

In this case our template would be placed in net_nemein_news/templates/nnn-show-article.php. It could contain something like:

<div class="hentry">
    <h1 tal:content="net_nemein_news/article/title" class="entry-title">Headline</h1>

    <div tal:content="net_nemein_news/article/metadata/published" class="published">2007-08-01</div>

    <div tal:content="structure net_nemein_news/article/content" class="entry-content">

The XHTML attributes in the tal namespace contain the rules used by TAL for replacing the example data with the real data from the controller. The data array of the controller is exposed to tal using the component name, in this case net_nemein_news.

The default template supplied by the component can be overridden by placing an element named nnn-show-article to either the site main style, or as an element of the current folder.

This is just the surface

This has been a very quick overview of the MidCOM framework. The third version framework is still very much evolving, but the earlier versions are already very rich with existing tools and features.

However, in near future MidCOM 3 will feature rich signal-based I/O event handling, Access Control Lists, caching and many other things useful to web developers.

Everybody interested in MidCOM 3 is welcome to install a Midgard 1.9 nightly, get a git checkout of MidCOM 3 and start playing.

Read more Midgard posts.