Tales of a Metal Cloud – Part 1

About reaching the goal and beautifying the path or Usability is also about the code (usability in the code?).
Metal Cloud

Many moons ago, when I unintentionally had ended up as a web developer, I had the pleasure of working for two small companies that both used Plone and hence ZPT - Zope Page Templates. After messing around with all kinds of ugly, inconsistent web coding, it was a relief to be able to use the clean markup that TAL provides, and seamlessly assemble pages using METAL.

Using Zope also had the benefit of having Python as it's backend scripting language. I don't want to dive into how much I prefer Python over PHP - enough has been said about that already - and I fully acknowledge that the ubiquity of PHP makes it the perfect choice for a project like ownCloud. Nor do I want to question the strength of the template class used in ownCloud; you can do practically everything. But the strength of OC_Template is IMHO also it's weakness.

During the few months I've been coding for ownCloud, ideas for it's usage have spawned, new apps pop up, code is being tweaked to do amazing stuff and soon the app repository will be "there's an app for that" also for ownCloud.

Being at the point where everyone can create and publish an app for ownCloud sets up some requirements:

  • Maintainability: If the app is ever abandoned, it has to be easy for a new maintainer to take over. This leads to:
  • Readability: No-one wants to maintain an app with poorly structured code and markup, or with none or insufficient documentation.
  • Validity: This is very broad and covers e.g. packaging, cross browser usability and that the markup adheres to common standards.
Maintain the beauty of the markup.

With the Template Attribute Language (TAL) we can achieve having beautifully structured markup, and the interpreter will let us know of any missing end tags or wrongly nested markup, as a matter of fact the page won't render if we mess it up.

The good thing is that some good people have made a PHP library that implements TAL, TALES and METAL, so I've made a proof of concept ownCloud integration using it, which actually works pretty well, if I may say so 😉

Time to show what this will mean for the template author. As example I use the form for editing the structured name data in the ownCloud Contacts app.
Below is how the currently used markup looks.

< ?php
$name = isset($_['name'])?$_['name']:'';
<div id="edit_name_dialog" title="Edit name">
	<dl class="form">
		<dt><label for="pre">< ?php echo $l->t('Hon. prefixes'); ?></label></dt>
			<input name="pre" id="pre" value="<?php echo isset($name[3]) ? $name[3] : ''; ?/>" type="text" list="prefixes" />
			<datalist id="prefixes">
				<option value="<?php echo $l->t('Mrs.'); ?>">
				</option><option value="<?php echo $l->t('Mr.'); ?>">
				</option><option value="<?php echo $l->t('Sir'); ?>">
				</option><option value="<?php echo $l->t('Dr.'); ?>">
		<dt><label for="giv">< ?php echo $l->t('Given name'); ?></label></dt>
		<dd><input name="giv" id="giv" value="<?php echo isset($name[1]) ? $name[1] : ''; ?/>" type="text" /></dd>
		<dt><label for="add">< ?php echo $l->t('Additional names'); ?></label></dt>
		<dd><input name="add" id="add" value="<?php echo isset($name[2]) ? $name[2] : ''; ?/>" type="text" /></dd>
		<dt><label for="fam">< ?php echo $l->t('Family name'); ?></label></dt>
		<dd><input name="fam" id="fam" value="<?php echo isset($name[0]) ? $name[0] : ''; ?/>" type="text" /></dd>
		<dt><label for="suf">< ?php echo $l->t('Hon. suffixes'); ?></label></dt>
			<input name="suf" id="suf" value="<?php echo isset($name[4]) ? $name[4] : ''; ?/>" type="text" list="suffixes" />
			<datalist id="suffixes">
				<option value="<?php echo $l->t('M.D.'); ?>">
				</option><option value="<?php echo $l->t('Ph.D.'); ?>">
				</option><option value="<?php echo $l->t('Jr.'); ?>">
				</option><option value="<?php echo $l->t('Sn.'); ?>">

This isn't exactly pretty, and if you want to use a visual HTML editor, it won't look good there either. And believe me, this isn't the worst looking example 😉
Let's see the same snippet edited for using TAL and TALES

<div id="edit_name_dialog" i18n:domain="contacts" i18n:attributes="title" title="Edit name">
	<fieldset tal:condition="name">
	<dl class="form">
		<dt><label for="pre">Hon. prefixes</label></dt>
			<input name="pre" id="pre" tal:attributes="value name/3|nothing" value="" type="text" list="prefixes" />
			<datalist id="prefixes">
				<option i18n:attributes="value" value="Mrs." />
				<option i18n:attributes="value" value="Mr." />
				<option i18n:attributes="value" value="Sir" />
				<option i18n:attributes="value" value="Dr" />
		<dt><label for="giv" i18n:translate="">Given name</label></dt>
		<dd><input name="giv" id="giv" tal:attributes="value name/1|nothing" value="" type="text" /></dd>
		<dt><label for="add" i18n:translate="">Additional names</label></dt>
		<dd><input name="add" id="add" tal:attributes="value name/2|nothing" value="" type="text" /></dd>
		<dt><label for="fam" i18n:translate="">Family name</label></dt>
		<dd><input name="fam" id="fam" tal:attributes="value name/0|nothing" value="" type="text" /></dd>
		<dt><label for="suf" i18n:translate="">Hon. suffixes</label></dt>
			<input name="suf" id="suf" tal:attributes="value name/4|nothing" value="" type="text" list="suffixes" />
			<datalist id="suffixes">
				<option i18n:attributes="value" value="M.D." />
				<option i18n:attributes="value" value="Ph.D." />
				<option i18n:attributes="value" value="Jr." />
				<option i18n:attributes="value" value="Sn." />

In part 1 I've shown the basics of using TAL, but this is only a foretaste of how PHPTAL can be used in ownCloud. In the next part - hopefully comming shortly - I will dig deeper into how to use it to render a full page, how to access variables, how to make use of the powerfull METAL macros and how I've plugged it all in to use ownClouds built-in authentication, template discovery and internationalization system.

In the meanwhile have a look at the resources below for information about TAL, TALES and METAL

Update: I wrote this article quite a while ago, but never got around to publishing it. In the mean time I've made my implementation available at https://github.com/tanghus/tal/ and made a Journal/Notes app utilizing it which is available at https://github.com/tanghus/journal/. I will publish both soon at the ownCloud app repository.
Update 2: The TAL Page Templates only works on current git master which will be released as ownCloud 5 in some time within the next couple of months 😉 Update 3: I have released TAL Page Templates for ownCloud 4.5 and it is available from the app repository, or from Settings/Apps when you have installed/upgraded to 4.5. At the same time I have released a small Journal/Notes app which uses the TAL templates.

Flattr this!


  1. 1
    Gomez says:

    Wow, great work!

    I am a Plone/Python developer and its great to see TAL/Metal in ownCloud. Its really one of the cleanest template engines out there.

    Thanks for your work, i plan to convert an OC3 App to Tal and oc4.

    Looking forward to part 2 of this series :)

    • 2
      tanghus says:

      Yes, I was thrilled when I found a PHP implementation. TAL has it's quirks, but compared to all the difficulties you get with mixing scripting into your markup it's all worth it.
      Fell free to clone the repository and come with suggestions/improvements :-)

      And I hope part 2 wont take as long time as part 1 did 😉

  2. 3
    eMerzh says:

    Template engines is like frameworks or programing languages, everyone has preferences for his own...

    But personnaly i really like the power of Twig , powerfull without reinventing the html and able to render other things than plain html (no text, feed, ...)

    • 4
      tanghus says:

      I had a quick look at Twig, and the syntax reminded me very much of a template engine I made with a coworker years ago - also in PHP. A lot cleaner than OC_Template, but I really dislike having the mix of different markup. That's what I like really like about TAL: you can (almost) always do the required logic in the attributes.
      But as you say it's a matter of preference :-)

  3. 5
    morrph says:

    Tried loading up the items you speak about and received this error.

    Fatal error: Call to undefined method OC_App::getAppPath() in /var/www/html/owncloud/apps/tal/lib/taltemplate.php on line 61

    Any ideas about the cause ?