Skip to content

Instantly share code, notes, and snippets.

@evansolomon
Created November 8, 2013 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evansolomon/7370101 to your computer and use it in GitHub Desktop.
Save evansolomon/7370101 to your computer and use it in GitHub Desktop.
<?php
/*
Example usage:
$template = new Medium_Template( 'Hi, I am {{name|html}}.' );
echo $template->compile( array( 'name' => '<b>Evan</b>' ) );
// Hi, I am &lt;b&gt;Evan&lt;/b&gt;.
echo $template->compile( array( 'name' => 'someone else' ) );
// Hi, I am someone else.
*/
/**
* A *very* simple mustache-style template utility.
*/
class Medium_Template {
/**
* Create a template instance with an (uncompiled) template string. Templates
* are a very basic version of mustache-style, plus an optional pipe-delimited
* escape callback. Escape callbacks are prefixed with esc_ by default.
*/
function __construct( $template ) {
$this->template = $template;
$this->pattern = '/\{{2}(.+?)\}{2}/';
$this->esc_delimiter = '|';
}
/**
* Return the compiled output of the template with the given data. Missing fields
* are interpretted as empty strings.
*/
function compile( $data ) {
$tokens = $this->get_tokens();
return $this->replace( $tokens, $data );
}
/**
* Get a list of replacement tokens without the surrounding identifiers.
*/
function get_tokens() {
preg_match_all( $this->pattern, $this->template, $matches );
return $matches[1];
}
/**
* Replace each token with its underlying data. Escape the data with its
* optional callback.
*/
function replace( $tokens, $data ) {
$template = $this->template;
foreach ( $tokens as $token ) {
$target = $this->wrap_token( $token );
$token_parts = $this->parse_token( $token );
$escape = $token_parts['escape'];
if ( isset( $data[ $token_parts['name'] ] ) ) {
$input = $data[ $token_parts['name'] ];
} else {
$input = '';
}
$replacement = $this->maybe_escape( $input, $escape );
$template = str_replace( $target, $replacement, $template );
}
return $template;
}
/**
* Convert a token to a replacement string.
*/
function wrap_token( $token ) {
return '{{' . $token . '}}';
}
/**
* Split a token into its name and optional escape callback.
*/
function parse_token( $token ) {
$data = array();
$parts = array_map( 'trim', explode( $this->esc_delimiter, $token ) );
$data['name'] = $parts[0];
$data['escape'] = count( $parts ) > 1 ? $parts[1] : false;
return $data;
}
/**
* Escape data with a callback only when the callback is valid.
*/
function maybe_escape( $data, $callback ) {
$callback = "esc_{$callback}";
if ( ! is_callable( $callback ) ) {
return $data;
}
return call_user_func( $callback, $data );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment