Recently, one of my clients added a site that leverages MojoMotor (MM) to the list of assets that I now help maintain and improve. MM has an almost Perch like philosophy about being a CMS: it's all about being as lightweight as possible. And to the credit folks behind MM, they have managed to put together a lean system.
MM uses a sort of tag based markup language to power its templates. While handy for simple tasks, I vastly prefer using PHP as a template language, rather than something ad hoc. Luckily, MojoMotor is easily extendable and in about 40 lines of code, I had a full PHP based template engine running within MojoMotor.
Now, a MM layout can contain code like:
<html>
<head>
{mojo:snippet:apply path="assets/js" src="foo.js"}
...
Which invokes snippets/assets/js.php and sets $src to the value foo.js. Within that file, I may have:
<?
/*
* Render a javascript include
*/
$xcache = calculate_our_cache_busting_value();
$should_mini = should_mini_files();
$src = $should_mini ? "/assets/mini/$src" : "/assets/full/$src";
?>
<script src="<?= $src ?>?xcache=<?=$xcache?>"
type="text/javascript">
Using this tiny function, it's possible to invoke one snippet (PHP template) from within another, making for easy abstractions.
To implement this in MM, I created the following directory structure:
system/mojomotor/third_party/snippet/index.html (an empty file) system/mojomotor/third_party/snippet/libraries/ system/mojomotor/third_party/snippet/libraries/snippet.php
Inside of snippet.php is this hunk of PHP code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/* CHANGE ME: At the top level of the source tree. */
define('SNIPPET_BASE_DIR', dirname(__FILE__) . '/../../../../../snippets');
/**
* Snippets are small chunks of HTML code that are
* imported and evaluated on the fly.
*/
class Snippet {
public function apply($template_data) {
$_path = $template_data['parameters']['path'];
unset($template_data['parameters']['path']);
if(!$_path) {
return "Snippet error: no path param";
}
if(!file_exists(SNIPPET_BASE_DIR . "/$_path.php")) {
return "Snippet error: not found: $_path";
}
$body = $template_data['tag_contents'];
extract($template_data['parameters']);
ob_start();
require(SNIPPET_BASE_DIR . "/$_path.php");
$content = ob_get_clean();
return $content;
}
}
?>
I'm sure there are optimizations to made (add caching of snippets, perhaps?), but as a quick and easy way to add a lot of power (and abstraction) to your templates, this approach is hard to beat.
No comments:
Post a Comment