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