Update to proposed PSR-1 coding standard.

* 4 space (no tab) indent
 * K&R-style braces
This commit is contained in:
Justin Hileman
2012-05-01 22:03:39 -07:00
parent be5cfb3e9e
commit 2448992cc8
57 changed files with 3283 additions and 3009 deletions
+33 -33
View File
@@ -38,10 +38,10 @@ define('EXAMPLE_PATH', realpath(dirname(__FILE__) . '/../test/fixtures/examples'
* @return string
*/
function getLowerCaseName($name) {
return preg_replace_callback("/([A-Z])/", create_function (
'$match',
'return "_" . strtolower($match[1]);'
), lcfirst($name));
return preg_replace_callback("/([A-Z])/", create_function (
'$match',
'return "_" . strtolower($match[1]);'
), lcfirst($name));
}
/**
@@ -57,10 +57,10 @@ function getLowerCaseName($name) {
* @return string
*/
function getUpperCaseName($name) {
return preg_replace_callback("/_([a-z])/", create_function (
'$match',
'return strtoupper($match{1});'
), ucfirst($name));
return preg_replace_callback("/_([a-z])/", create_function (
'$match',
'return strtoupper($match{1});'
), ucfirst($name));
}
@@ -72,8 +72,8 @@ function getUpperCaseName($name) {
* @return mixed
*/
function out($value) {
echo $value . "\n";
return $value;
echo $value . "\n";
return $value;
}
/**
@@ -89,8 +89,8 @@ function out($value) {
* @return string
*/
function buildPath($directory, $filename = null, $extension = null) {
return out(EXAMPLE_PATH . '/' . $directory.
($extension !== null && $filename !== null ? '/' . $filename. "." . $extension : ""));
return out(EXAMPLE_PATH . '/' . $directory.
($extension !== null && $filename !== null ? '/' . $filename. "." . $extension : ""));
}
/**
@@ -102,9 +102,9 @@ function buildPath($directory, $filename = null, $extension = null) {
* @return void
*/
function createDirectory($directory) {
if(!@mkdir(buildPath($directory))) {
die("FAILED to create directory\n");
}
if(!@mkdir(buildPath($directory))) {
die("FAILED to create directory\n");
}
}
/**
@@ -119,13 +119,13 @@ function createDirectory($directory) {
* @return void
*/
function createFile($directory, $filename, $extension, $content = "") {
$handle = @fopen(buildPath($directory, $filename, $extension), "w");
if($handle) {
fwrite($handle, $content);
fclose($handle);
} else {
die("FAILED to create file\n");
}
$handle = @fopen(buildPath($directory, $filename, $extension), "w");
if($handle) {
fwrite($handle, $content);
fclose($handle);
} else {
die("FAILED to create file\n");
}
}
@@ -143,12 +143,12 @@ function createFile($directory, $filename, $extension, $content = "") {
* @return void
*/
function main($example_name) {
$lowercase = getLowerCaseName($example_name);
$uppercase = getUpperCaseName($example_name);
createDirectory($lowercase);
createFile($lowercase, $lowercase, "mustache");
createFile($lowercase, $lowercase, "txt");
createFile($lowercase, $uppercase, "php", <<<CONTENT
$lowercase = getLowerCaseName($example_name);
$uppercase = getUpperCaseName($example_name);
createDirectory($lowercase);
createFile($lowercase, $lowercase, "mustache");
createFile($lowercase, $lowercase, "txt");
createFile($lowercase, $uppercase, "php", <<<CONTENT
<?php
class {$uppercase} {
@@ -156,16 +156,16 @@ class {$uppercase} {
}
CONTENT
);
);
}
// check if enougth arguments are given
if(count($argv) > 1) {
// get the name of the example
$example_name = $argv[1];
// get the name of the example
$example_name = $argv[1];
main($example_name);
main($example_name);
} else {
echo USAGE;
echo USAGE;
}
+47 -43
View File
@@ -12,54 +12,58 @@
/**
* Mustache class autoloader.
*/
class Mustache_Autoloader {
class Mustache_Autoloader
{
private $baseDir;
private $baseDir;
/**
* Autoloader constructor.
*
* @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
*/
public function __construct($baseDir = null) {
if ($baseDir === null) {
$this->baseDir = dirname(__FILE__).'/..';
} else {
$this->baseDir = rtrim($baseDir, '/');
}
}
/**
* Autoloader constructor.
*
* @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
*/
public function __construct($baseDir = null)
{
if ($baseDir === null) {
$this->baseDir = dirname(__FILE__).'/..';
} else {
$this->baseDir = rtrim($baseDir, '/');
}
}
/**
* Register a new instance as an SPL autoloader.
*
* @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
*
* @return Mustache_Autoloader Registered Autoloader instance
*/
static public function register($baseDir = null) {
$loader = new self($baseDir);
spl_autoload_register(array($loader, 'autoload'));
/**
* Register a new instance as an SPL autoloader.
*
* @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
*
* @return Mustache_Autoloader Registered Autoloader instance
*/
static public function register($baseDir = null)
{
$loader = new self($baseDir);
spl_autoload_register(array($loader, 'autoload'));
return $loader;
}
return $loader;
}
/**
* Autoload Mustache classes.
*
* @param string $class
*/
public function autoload($class) {
if ($class[0] === '\\') {
$class = substr($class, 1);
}
/**
* Autoload Mustache classes.
*
* @param string $class
*/
public function autoload($class)
{
if ($class[0] === '\\') {
$class = substr($class, 1);
}
if (strpos($class, 'Mustache') !== 0) {
return;
}
if (strpos($class, 'Mustache') !== 0) {
return;
}
$file = sprintf('%s/%s.php', $this->baseDir, str_replace('_', '/', $class));
if (is_file($file)) {
require $file;
}
}
$file = sprintf('%s/%s.php', $this->baseDir, str_replace('_', '/', $class));
if (is_file($file)) {
require $file;
}
}
}
+321 -306
View File
@@ -14,355 +14,370 @@
*
* This class is responsible for turning a Mustache token parse tree into normal PHP source code.
*/
class Mustache_Compiler {
class Mustache_Compiler
{
private $sections;
private $source;
private $indentNextLine;
private $customEscape;
private $charset;
private $sections;
private $source;
private $indentNextLine;
private $customEscape;
private $charset;
/**
* Compile a Mustache token parse tree into PHP source code.
*
* @param string $source Mustache Template source code
* @param string $tree Parse tree of Mustache tokens
* @param string $name Mustache Template class name
*
* @return string Generated PHP source code
*/
public function compile($source, array $tree, $name, $customEscape = false, $charset = 'UTF-8') {
$this->sections = array();
$this->source = $source;
$this->indentNextLine = true;
$this->customEscape = $customEscape;
$this->charset = $charset;
/**
* Compile a Mustache token parse tree into PHP source code.
*
* @param string $source Mustache Template source code
* @param string $tree Parse tree of Mustache tokens
* @param string $name Mustache Template class name
*
* @return string Generated PHP source code
*/
public function compile($source, array $tree, $name, $customEscape = false, $charset = 'UTF-8')
{
$this->sections = array();
$this->source = $source;
$this->indentNextLine = true;
$this->customEscape = $customEscape;
$this->charset = $charset;
return $this->writeCode($tree, $name);
}
return $this->writeCode($tree, $name);
}
/**
* Helper function for walking the Mustache token parse tree.
*
* @throws InvalidArgumentException upon encountering unknown token types.
*
* @param array $tree Parse tree of Mustache tokens
* @param int $level (default: 0)
*
* @return string Generated PHP source code;
*/
private function walk(array $tree, $level = 0) {
$code = '';
$level++;
foreach ($tree as $node) {
switch ($node[Mustache_Tokenizer::TYPE]) {
case Mustache_Tokenizer::T_SECTION:
$code .= $this->section(
$node[Mustache_Tokenizer::NODES],
$node[Mustache_Tokenizer::NAME],
$node[Mustache_Tokenizer::INDEX],
$node[Mustache_Tokenizer::END],
$node[Mustache_Tokenizer::OTAG],
$node[Mustache_Tokenizer::CTAG],
$level
);
break;
/**
* Helper function for walking the Mustache token parse tree.
*
* @throws InvalidArgumentException upon encountering unknown token types.
*
* @param array $tree Parse tree of Mustache tokens
* @param int $level (default: 0)
*
* @return string Generated PHP source code;
*/
private function walk(array $tree, $level = 0)
{
$code = '';
$level++;
foreach ($tree as $node) {
switch ($node[Mustache_Tokenizer::TYPE]) {
case Mustache_Tokenizer::T_SECTION:
$code .= $this->section(
$node[Mustache_Tokenizer::NODES],
$node[Mustache_Tokenizer::NAME],
$node[Mustache_Tokenizer::INDEX],
$node[Mustache_Tokenizer::END],
$node[Mustache_Tokenizer::OTAG],
$node[Mustache_Tokenizer::CTAG],
$level
);
break;
case Mustache_Tokenizer::T_INVERTED:
$code .= $this->invertedSection(
$node[Mustache_Tokenizer::NODES],
$node[Mustache_Tokenizer::NAME],
$level
);
break;
case Mustache_Tokenizer::T_INVERTED:
$code .= $this->invertedSection(
$node[Mustache_Tokenizer::NODES],
$node[Mustache_Tokenizer::NAME],
$level
);
break;
case Mustache_Tokenizer::T_PARTIAL:
case Mustache_Tokenizer::T_PARTIAL_2:
$code .= $this->partial(
$node[Mustache_Tokenizer::NAME],
isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '',
$level
);
break;
case Mustache_Tokenizer::T_PARTIAL:
case Mustache_Tokenizer::T_PARTIAL_2:
$code .= $this->partial(
$node[Mustache_Tokenizer::NAME],
isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '',
$level
);
break;
case Mustache_Tokenizer::T_UNESCAPED:
case Mustache_Tokenizer::T_UNESCAPED_2:
$code .= $this->variable($node[Mustache_Tokenizer::NAME], false, $level);
break;
case Mustache_Tokenizer::T_UNESCAPED:
case Mustache_Tokenizer::T_UNESCAPED_2:
$code .= $this->variable($node[Mustache_Tokenizer::NAME], false, $level);
break;
case Mustache_Tokenizer::T_COMMENT:
break;
case Mustache_Tokenizer::T_COMMENT:
break;
case Mustache_Tokenizer::T_ESCAPED:
$code .= $this->variable($node[Mustache_Tokenizer::NAME], true, $level);
break;
case Mustache_Tokenizer::T_ESCAPED:
$code .= $this->variable($node[Mustache_Tokenizer::NAME], true, $level);
break;
case Mustache_Tokenizer::T_TEXT:
$code .= $this->text($node[Mustache_Tokenizer::VALUE], $level);
break;
case Mustache_Tokenizer::T_TEXT:
$code .= $this->text($node[Mustache_Tokenizer::VALUE], $level);
break;
default:
throw new InvalidArgumentException('Unknown node type: '.json_encode($node));
}
}
default:
throw new InvalidArgumentException('Unknown node type: '.json_encode($node));
}
}
return $code;
}
return $code;
}
const KLASS = '<?php
const KLASS = '<?php
class %s extends Mustache_Template {
public function renderInternal(Mustache_Context $context, $indent = \'\', $escape = false) {
$buffer = \'\';
%s
class %s extends Mustache_Template
{
public function renderInternal(Mustache_Context $context, $indent = \'\', $escape = false)
{
$buffer = \'\';
%s
if ($escape) {
return %s;
} else {
return $buffer;
}
}
%s
}';
if ($escape) {
return %s;
} else {
return $buffer;
}
}
%s
}';
/**
* Generate Mustache Template class PHP source.
*
* @param array $tree Parse tree of Mustache tokens
* @param string $name Mustache Template class name
*
* @return string Generated PHP source code
*/
private function writeCode($tree, $name) {
$code = $this->walk($tree);
$sections = implode("\n", $this->sections);
/**
* Generate Mustache Template class PHP source.
*
* @param array $tree Parse tree of Mustache tokens
* @param string $name Mustache Template class name
*
* @return string Generated PHP source code
*/
private function writeCode($tree, $name)
{
$code = $this->walk($tree);
$sections = implode("\n", $this->sections);
return sprintf($this->prepare(self::KLASS, 0, false), $name, $code, $this->getEscape('$buffer'), $sections);
}
return sprintf($this->prepare(self::KLASS, 0, false), $name, $code, $this->getEscape('$buffer'), $sections);
}
const SECTION_CALL = '
// %s section
$buffer .= $this->section%s($context, $indent, $context->%s(%s));
';
const SECTION_CALL = '
// %s section
$buffer .= $this->section%s($context, $indent, $context->%s(%s));
';
const SECTION = '
private function section%s(Mustache_Context $context, $indent, $value) {
$buffer = \'\';
if (!is_string($value) && is_callable($value)) {
$source = %s;
$buffer .= $this->mustache
->loadLambda((string) call_user_func($value, $source)%s)
->renderInternal($context, $indent);
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);%s
$context->pop();
}
}
const SECTION = '
private function section%s(Mustache_Context $context, $indent, $value) {
$buffer = \'\';
if (!is_string($value) && is_callable($value)) {
$source = %s;
$buffer .= $this->mustache
->loadLambda((string) call_user_func($value, $source)%s)
->renderInternal($context, $indent);
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);%s
$context->pop();
}
}
return $buffer;
}';
return $buffer;
}';
/**
* Generate Mustache Template section PHP source.
*
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param int $start Section start offset
* @param int $end Section end offset
* @param string $otag Current Mustache opening tag
* @param string $ctag Current Mustache closing tag
* @param int $level
*
* @return string Generated section PHP source code
*/
private function section($nodes, $id, $start, $end, $otag, $ctag, $level) {
$method = $this->getFindMethod($id);
$id = var_export($id, true);
$source = var_export(substr($this->source, $start, $end - $start), true);
/**
* Generate Mustache Template section PHP source.
*
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param int $start Section start offset
* @param int $end Section end offset
* @param string $otag Current Mustache opening tag
* @param string $ctag Current Mustache closing tag
* @param int $level
*
* @return string Generated section PHP source code
*/
private function section($nodes, $id, $start, $end, $otag, $ctag, $level)
{
$method = $this->getFindMethod($id);
$id = var_export($id, true);
$source = var_export(substr($this->source, $start, $end - $start), true);
if ($otag !== '{{' || $ctag !== '}}') {
$delims = ', '.var_export(sprintf('{{= %s %s =}}', $otag, $ctag), true);
} else {
$delims = '';
}
if ($otag !== '{{' || $ctag !== '}}') {
$delims = ', '.var_export(sprintf('{{= %s %s =}}', $otag, $ctag), true);
} else {
$delims = '';
}
$key = ucfirst(md5($delims."\n".$source));
$key = ucfirst(md5($delims."\n".$source));
if (!isset($this->sections[$key])) {
$this->sections[$key] = sprintf($this->prepare(self::SECTION), $key, $source, $delims, $this->walk($nodes, 2));
}
if (!isset($this->sections[$key])) {
$this->sections[$key] = sprintf($this->prepare(self::SECTION), $key, $source, $delims, $this->walk($nodes, 2));
}
return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $key, $method, $id);
}
return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $key, $method, $id);
}
const INVERTED_SECTION = '
// %s inverted section
$value = $context->%s(%s);
if (empty($value)) {
%s
}';
const INVERTED_SECTION = '
// %s inverted section
$value = $context->%s(%s);
if (empty($value)) {
%s
}';
/**
* Generate Mustache Template inverted section PHP source.
*
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param int $level
*
* @return string Generated inverted section PHP source code
*/
private function invertedSection($nodes, $id, $level) {
$method = $this->getFindMethod($id);
$id = var_export($id, true);
/**
* Generate Mustache Template inverted section PHP source.
*
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param int $level
*
* @return string Generated inverted section PHP source code
*/
private function invertedSection($nodes, $id, $level)
{
$method = $this->getFindMethod($id);
$id = var_export($id, true);
return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $this->walk($nodes, $level));
}
return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $this->walk($nodes, $level));
}
const PARTIAL = '
if ($partial = $this->mustache->loadPartial(%s)) {
$buffer .= $partial->renderInternal($context, %s);
}
';
const PARTIAL = '
if ($partial = $this->mustache->loadPartial(%s)) {
$buffer .= $partial->renderInternal($context, %s);
}
';
/**
* Generate Mustache Template partial call PHP source.
*
* @param string $id Partial name
* @param string $indent Whitespace indent to apply to partial
* @param int $level
*
* @return string Generated partial call PHP source code
*/
private function partial($id, $indent, $level) {
return sprintf(
$this->prepare(self::PARTIAL, $level),
var_export($id, true),
var_export($indent, true)
);
}
/**
* Generate Mustache Template partial call PHP source.
*
* @param string $id Partial name
* @param string $indent Whitespace indent to apply to partial
* @param int $level
*
* @return string Generated partial call PHP source code
*/
private function partial($id, $indent, $level)
{
return sprintf(
$this->prepare(self::PARTIAL, $level),
var_export($id, true),
var_export($indent, true)
);
}
const VARIABLE = '
$value = $context->%s(%s);
if (!is_string($value) && is_callable($value)) {
$value = $this->mustache
->loadLambda((string) call_user_func($value))
->renderInternal($context, $indent);
}
$buffer .= %s%s;
';
const VARIABLE = '
$value = $context->%s(%s);
if (!is_string($value) && is_callable($value)) {
$value = $this->mustache
->loadLambda((string) call_user_func($value))
->renderInternal($context, $indent);
}
$buffer .= %s%s;
';
/**
* Generate Mustache Template variable interpolation PHP source.
*
* @param string $id Variable name
* @param boolean $escape Escape the variable value for output?
* @param int $level
*
* @return string Generated variable interpolation PHP source
*/
private function variable($id, $escape, $level) {
$method = $this->getFindMethod($id);
$id = ($method !== 'last') ? var_export($id, true) : '';
$value = $escape ? $this->getEscape() : '$value';
/**
* Generate Mustache Template variable interpolation PHP source.
*
* @param string $id Variable name
* @param boolean $escape Escape the variable value for output?
* @param int $level
*
* @return string Generated variable interpolation PHP source
*/
private function variable($id, $escape, $level)
{
$method = $this->getFindMethod($id);
$id = ($method !== 'last') ? var_export($id, true) : '';
$value = $escape ? $this->getEscape() : '$value';
return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $this->flushIndent(), $value);
}
return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $this->flushIndent(), $value);
}
const LINE = '$buffer .= "\n";';
const TEXT = '$buffer .= %s%s;';
const LINE = '$buffer .= "\n";';
const TEXT = '$buffer .= %s%s;';
/**
* Generate Mustache Template output Buffer call PHP source.
*
* @param string $text
* @param int $level
*
* @return string Generated output Buffer call PHP source
*/
private function text($text, $level) {
if ($text === "\n") {
$this->indentNextLine = true;
/**
* Generate Mustache Template output Buffer call PHP source.
*
* @param string $text
* @param int $level
*
* @return string Generated output Buffer call PHP source
*/
private function text($text, $level)
{
if ($text === "\n") {
$this->indentNextLine = true;
return $this->prepare(self::LINE, $level);
} else {
return sprintf($this->prepare(self::TEXT, $level), $this->flushIndent(), var_export($text, true));
}
}
return $this->prepare(self::LINE, $level);
} else {
return sprintf($this->prepare(self::TEXT, $level), $this->flushIndent(), var_export($text, true));
}
}
/**
* Prepare PHP source code snippet for output.
*
* @param string $text
* @param int $bonus Additional indent level (default: 0)
* @param boolean $prependNewline Prepend a newline to the snippet? (default: true)
*
* @return string PHP source code snippet
*/
private function prepare($text, $bonus = 0, $prependNewline = true) {
$text = ($prependNewline ? "\n" : '').trim($text);
if ($prependNewline) {
$bonus++;
}
/**
* Prepare PHP source code snippet for output.
*
* @param string $text
* @param int $bonus Additional indent level (default: 0)
* @param boolean $prependNewline Prepend a newline to the snippet? (default: true)
*
* @return string PHP source code snippet
*/
private function prepare($text, $bonus = 0, $prependNewline = true)
{
$text = ($prependNewline ? "\n" : '').trim($text);
if ($prependNewline) {
$bonus++;
}
return preg_replace("/\n(\t\t)?/", "\n".str_repeat("\t", $bonus), $text);
}
return preg_replace("/\n( {8})?/", "\n".str_repeat(" ", $bonus * 4), $text);
}
const DEFAULT_ESCAPE = 'htmlspecialchars(%s, ENT_COMPAT, %s)';
const CUSTOM_ESCAPE = 'call_user_func($this->mustache->getEscape(), %s)';
const DEFAULT_ESCAPE = 'htmlspecialchars(%s, ENT_COMPAT, %s)';
const CUSTOM_ESCAPE = 'call_user_func($this->mustache->getEscape(), %s)';
/**
* Get the current escaper.
*
* @return string Either a custom callback, or an inline call to `htmlspecialchars`
*/
private function getEscape($value = '$value') {
if ($this->customEscape) {
return sprintf(self::CUSTOM_ESCAPE, $value);
} else {
return sprintf(self::DEFAULT_ESCAPE, $value, var_export($this->charset, true));
}
}
/**
* Get the current escaper.
*
* @return string Either a custom callback, or an inline call to `htmlspecialchars`
*/
private function getEscape($value = '$value')
{
if ($this->customEscape) {
return sprintf(self::CUSTOM_ESCAPE, $value);
} else {
return sprintf(self::DEFAULT_ESCAPE, $value, var_export($this->charset, true));
}
}
/**
* Select the appropriate Context `find` method for a given $id.
*
* The return value will be one of `find`, `findDot` or `last`.
*
* @see Mustache_Context::find
* @see Mustache_Context::findDot
* @see Mustache_Context::last
*
* @param string $id Variable name
*
* @return string `find` method name
*/
private function getFindMethod($id) {
if ($id === '.') {
return 'last';
} elseif (strpos($id, '.') === false) {
return 'find';
} else {
return 'findDot';
}
}
/**
* Select the appropriate Context `find` method for a given $id.
*
* The return value will be one of `find`, `findDot` or `last`.
*
* @see Mustache_Context::find
* @see Mustache_Context::findDot
* @see Mustache_Context::last
*
* @param string $id Variable name
*
* @return string `find` method name
*/
private function getFindMethod($id)
{
if ($id === '.') {
return 'last';
} elseif (strpos($id, '.') === false) {
return 'find';
} else {
return 'findDot';
}
}
const LINE_INDENT = '$indent . ';
const LINE_INDENT = '$indent . ';
/**
* Get the current $indent prefix to write to the buffer.
*
* @return string "$indent . " or ""
*/
private function flushIndent() {
if ($this->indentNextLine) {
$this->indentNextLine = false;
/**
* Get the current $indent prefix to write to the buffer.
*
* @return string "$indent . " or ""
*/
private function flushIndent()
{
if ($this->indentNextLine) {
$this->indentNextLine = false;
return self::LINE_INDENT;
} else {
return '';
}
}
return self::LINE_INDENT;
} else {
return '';
}
}
}
+123 -115
View File
@@ -12,130 +12,138 @@
/**
* Mustache Template rendering Context.
*/
class Mustache_Context {
private $stack = array();
class Mustache_Context
{
private $stack = array();
/**
* Mustache rendering Context constructor.
*
* @param mixed $context Default rendering context (default: null)
*/
public function __construct($context = null) {
if ($context !== null) {
$this->stack = array($context);
}
}
/**
* Mustache rendering Context constructor.
*
* @param mixed $context Default rendering context (default: null)
*/
public function __construct($context = null)
{
if ($context !== null) {
$this->stack = array($context);
}
}
/**
* Push a new Context frame onto the stack.
*
* @param mixed $value Object or array to use for context
*/
public function push($value) {
array_push($this->stack, $value);
}
/**
* Push a new Context frame onto the stack.
*
* @param mixed $value Object or array to use for context
*/
public function push($value)
{
array_push($this->stack, $value);
}
/**
* Pop the last Context frame from the stack.
*
* @return mixed Last Context frame (object or array)
*/
public function pop() {
return array_pop($this->stack);
}
/**
* Pop the last Context frame from the stack.
*
* @return mixed Last Context frame (object or array)
*/
public function pop()
{
return array_pop($this->stack);
}
/**
* Get the last Context frame.
*
* @return mixed Last Context frame (object or array)
*/
public function last() {
return end($this->stack);
}
/**
* Get the last Context frame.
*
* @return mixed Last Context frame (object or array)
*/
public function last()
{
return end($this->stack);
}
/**
* Find a variable in the Context stack.
*
* Starting with the last Context frame (the context of the innermost section), and working back to the top-level
* rendering context, look for a variable with the given name:
*
* * If the Context frame is an associative array which contains the key $id, returns the value of that element.
* * If the Context frame is an object, this will check first for a public method, then a public property named
* $id. Failing both of these, it will try `__isset` and `__get` magic methods.
* * If a value named $id is not found in any Context frame, returns an empty string.
*
* @param string $id Variable name
*
* @return mixed Variable value, or '' if not found
*/
public function find($id) {
return $this->findVariableInStack($id, $this->stack);
}
/**
* Find a variable in the Context stack.
*
* Starting with the last Context frame (the context of the innermost section), and working back to the top-level
* rendering context, look for a variable with the given name:
*
* * If the Context frame is an associative array which contains the key $id, returns the value of that element.
* * If the Context frame is an object, this will check first for a public method, then a public property named
* $id. Failing both of these, it will try `__isset` and `__get` magic methods.
* * If a value named $id is not found in any Context frame, returns an empty string.
*
* @param string $id Variable name
*
* @return mixed Variable value, or '' if not found
*/
public function find($id)
{
return $this->findVariableInStack($id, $this->stack);
}
/**
* Find a 'dot notation' variable in the Context stack.
*
* Note that dot notation traversal bubbles through scope differently than the regular find method. After finding
* the initial chunk of the dotted name, each subsequent chunk is searched for only within the value of the previous
* result. For example, given the following context stack:
*
* $data = array(
* 'name' => 'Fred',
* 'child' => array(
* 'name' => 'Bob'
* ),
* );
*
* ... and the Mustache following template:
*
* {{ child.name }}
*
* ... the `name` value is only searched for within the `child` value of the global Context, not within parent
* Context frames.
*
* @param string $id Dotted variable selector
*
* @return mixed Variable value, or '' if not found
*/
public function findDot($id) {
$chunks = explode('.', $id);
$first = array_shift($chunks);
$value = $this->findVariableInStack($first, $this->stack);
/**
* Find a 'dot notation' variable in the Context stack.
*
* Note that dot notation traversal bubbles through scope differently than the regular find method. After finding
* the initial chunk of the dotted name, each subsequent chunk is searched for only within the value of the previous
* result. For example, given the following context stack:
*
* $data = array(
* 'name' => 'Fred',
* 'child' => array(
* 'name' => 'Bob'
* ),
* );
*
* ... and the Mustache following template:
*
* {{ child.name }}
*
* ... the `name` value is only searched for within the `child` value of the global Context, not within parent
* Context frames.
*
* @param string $id Dotted variable selector
*
* @return mixed Variable value, or '' if not found
*/
public function findDot($id)
{
$chunks = explode('.', $id);
$first = array_shift($chunks);
$value = $this->findVariableInStack($first, $this->stack);
foreach ($chunks as $chunk) {
if ($value === '') {
return $value;
}
foreach ($chunks as $chunk) {
if ($value === '') {
return $value;
}
$value = $this->findVariableInStack($chunk, array($value));
}
$value = $this->findVariableInStack($chunk, array($value));
}
return $value;
}
return $value;
}
/**
* Helper function to find a variable in the Context stack.
*
* @see Mustache_Context::find
*
* @param string $id Variable name
* @param array $stack Context stack
*
* @return mixed Variable value, or '' if not found
*/
private function findVariableInStack($id, array $stack) {
for ($i = count($stack) - 1; $i >= 0; $i--) {
if (is_object($stack[$i])) {
if (method_exists($stack[$i], $id)) {
return $stack[$i]->$id();
} elseif (isset($stack[$i]->$id)) {
return $stack[$i]->$id;
}
} elseif (is_array($stack[$i]) && array_key_exists($id, $stack[$i])) {
return $stack[$i][$id];
}
}
/**
* Helper function to find a variable in the Context stack.
*
* @see Mustache_Context::find
*
* @param string $id Variable name
* @param array $stack Context stack
*
* @return mixed Variable value, or '' if not found
*/
private function findVariableInStack($id, array $stack)
{
for ($i = count($stack) - 1; $i >= 0; $i--) {
if (is_object($stack[$i])) {
if (method_exists($stack[$i], $id)) {
return $stack[$i]->$id();
} elseif (isset($stack[$i]->$id)) {
return $stack[$i]->$id;
}
} elseif (is_array($stack[$i]) && array_key_exists($id, $stack[$i])) {
return $stack[$i][$id];
}
}
return '';
}
return '';
}
}
+504 -472
View File
File diff suppressed because it is too large Load Diff
+139 -127
View File
@@ -12,145 +12,157 @@
/**
* A collection of helpers for a Mustache instance.
*/
class Mustache_HelperCollection {
private $helpers = array();
class Mustache_HelperCollection
{
private $helpers = array();
/**
* Helper Collection constructor.
*
* Optionally accepts an array (or Traversable) of `$name => $helper` pairs.
*
* @throws InvalidArgumentException if the $helpers argument isn't an array or Traversable
*
* @param array|Traversable $helpers (default: null)
*/
public function __construct($helpers = null) {
if ($helpers !== null) {
if (!is_array($helpers) && !$helpers instanceof Traversable) {
throw new InvalidArgumentException('HelperCollection constructor expects an array of helpers');
}
/**
* Helper Collection constructor.
*
* Optionally accepts an array (or Traversable) of `$name => $helper` pairs.
*
* @throws InvalidArgumentException if the $helpers argument isn't an array or Traversable
*
* @param array|Traversable $helpers (default: null)
*/
public function __construct($helpers = null)
{
if ($helpers !== null) {
if (!is_array($helpers) && !$helpers instanceof Traversable) {
throw new InvalidArgumentException('HelperCollection constructor expects an array of helpers');
}
foreach ($helpers as $name => $helper) {
$this->add($name, $helper);
}
}
}
foreach ($helpers as $name => $helper) {
$this->add($name, $helper);
}
}
}
/**
* Magic mutator.
*
* @see Mustache_HelperCollection::add
*
* @param string $name
* @param mixed $helper
*/
public function __set($name, $helper) {
$this->add($name, $helper);
}
/**
* Magic mutator.
*
* @see Mustache_HelperCollection::add
*
* @param string $name
* @param mixed $helper
*/
public function __set($name, $helper)
{
$this->add($name, $helper);
}
/**
* Add a helper to this collection.
*
* @param string $name
* @param mixed $helper
*/
public function add($name, $helper) {
$this->helpers[$name] = $helper;
}
/**
* Add a helper to this collection.
*
* @param string $name
* @param mixed $helper
*/
public function add($name, $helper)
{
$this->helpers[$name] = $helper;
}
/**
* Magic accessor.
*
* @see Mustache_HelperCollection::get
*
* @param string $name
*
* @return mixed Helper
*/
public function __get($name) {
return $this->get($name);
}
/**
* Magic accessor.
*
* @see Mustache_HelperCollection::get
*
* @param string $name
*
* @return mixed Helper
*/
public function __get($name)
{
return $this->get($name);
}
/**
* Get a helper by name.
*
* @param string $name
*
* @return mixed Helper
*/
public function get($name) {
if (!$this->has($name)) {
throw new InvalidArgumentException('Unknown helper: '.$name);
}
/**
* Get a helper by name.
*
* @param string $name
*
* @return mixed Helper
*/
public function get($name)
{
if (!$this->has($name)) {
throw new InvalidArgumentException('Unknown helper: '.$name);
}
return $this->helpers[$name];
}
return $this->helpers[$name];
}
/**
* Magic isset().
*
* @see Mustache_HelperCollection::has
*
* @param string $name
*
* @return boolean True if helper is present
*/
public function __isset($name) {
return $this->has($name);
}
/**
* Magic isset().
*
* @see Mustache_HelperCollection::has
*
* @param string $name
*
* @return boolean True if helper is present
*/
public function __isset($name)
{
return $this->has($name);
}
/**
* Check whether a given helper is present in the collection.
*
* @param string $name
*
* @return boolean True if helper is present
*/
public function has($name) {
return array_key_exists($name, $this->helpers);
}
/**
* Check whether a given helper is present in the collection.
*
* @param string $name
*
* @return boolean True if helper is present
*/
public function has($name)
{
return array_key_exists($name, $this->helpers);
}
/**
* Magic unset().
*
* @see Mustache_HelperCollection::remove
*
* @param string $name
*/
public function __unset($name) {
$this->remove($name);
}
/**
* Magic unset().
*
* @see Mustache_HelperCollection::remove
*
* @param string $name
*/
public function __unset($name)
{
$this->remove($name);
}
/**
* Check whether a given helper is present in the collection.
*
* @throws InvalidArgumentException if the requested helper is not present.
*
* @param string $name
*/
public function remove($name) {
if (!$this->has($name)) {
throw new InvalidArgumentException('Unknown helper: '.$name);
}
/**
* Check whether a given helper is present in the collection.
*
* @throws InvalidArgumentException if the requested helper is not present.
*
* @param string $name
*/
public function remove($name)
{
if (!$this->has($name)) {
throw new InvalidArgumentException('Unknown helper: '.$name);
}
unset($this->helpers[$name]);
}
unset($this->helpers[$name]);
}
/**
* Clear the helper collection.
*
* Removes all helpers from this collection
*/
public function clear() {
$this->helpers = array();
}
/**
* Clear the helper collection.
*
* Removes all helpers from this collection
*/
public function clear()
{
$this->helpers = array();
}
/**
* Check whether the helper collection is empty.
*
* @return boolean True if the collection is empty
*/
public function isEmpty() {
return empty($this->helpers);
}
/**
* Check whether the helper collection is empty.
*
* @return boolean True if the collection is empty
*/
public function isEmpty()
{
return empty($this->helpers);
}
}
+10 -9
View File
@@ -12,14 +12,15 @@
/**
* Mustache Template Loader interface.
*/
interface Mustache_Loader {
interface Mustache_Loader
{
/**
* Load a Template by name.
*
* @param string $name
*
* @return string Mustache Template source
*/
function load($name);
/**
* Load a Template by name.
*
* @param string $name
*
* @return string Mustache Template source
*/
public function load($name);
}
+44 -39
View File
@@ -27,48 +27,53 @@
* @implements Loader
* @implements MutableLoader
*/
class Mustache_Loader_ArrayLoader implements Mustache_Loader, Mustache_Loader_MutableLoader {
class Mustache_Loader_ArrayLoader implements Mustache_Loader, Mustache_Loader_MutableLoader
{
/**
* ArrayLoader constructor.
*
* @param array $templates Associative array of Template source (default: array())
*/
public function __construct(array $templates = array()) {
$this->templates = $templates;
}
/**
* ArrayLoader constructor.
*
* @param array $templates Associative array of Template source (default: array())
*/
public function __construct(array $templates = array())
{
$this->templates = $templates;
}
/**
* Load a Template.
*
* @param string $name
*
* @return string Mustache Template source
*/
public function load($name) {
if (!isset($this->templates[$name])) {
throw new InvalidArgumentException('Template '.$name.' not found.');
}
/**
* Load a Template.
*
* @param string $name
*
* @return string Mustache Template source
*/
public function load($name)
{
if (!isset($this->templates[$name])) {
throw new InvalidArgumentException('Template '.$name.' not found.');
}
return $this->templates[$name];
}
return $this->templates[$name];
}
/**
* Set an associative array of Template sources for this loader.
*
* @param array $templates
*/
public function setTemplates(array $templates) {
$this->templates = $templates;
}
/**
* Set an associative array of Template sources for this loader.
*
* @param array $templates
*/
public function setTemplates(array $templates)
{
$this->templates = $templates;
}
/**
* Set a Template source by name.
*
* @param string $name
* @param string $template Mustache Template source
*/
public function setTemplate($name, $template) {
$this->templates[$name] = $template;
}
/**
* Set a Template source by name.
*
* @param string $name
* @param string $template Mustache Template source
*/
public function setTemplate($name, $template)
{
$this->templates[$name] = $template;
}
}
+79 -74
View File
@@ -26,88 +26,93 @@
*
* @implements Loader
*/
class Mustache_Loader_FilesystemLoader implements Mustache_Loader {
private $baseDir;
private $extension = '.mustache';
private $templates = array();
class Mustache_Loader_FilesystemLoader implements Mustache_Loader
{
private $baseDir;
private $extension = '.mustache';
private $templates = array();
/**
* Mustache filesystem Loader constructor.
*
* Passing an $options array allows overriding certain Loader options during instantiation:
*
* $options = array(
* // The filename extension used for Mustache templates. Defaults to '.mustache'
* 'extension' => '.ms',
* );
*
* @throws RuntimeException if $baseDir does not exist.
*
* @param string $baseDir Base directory containing Mustache template files.
* @param array $options Array of Loader options (default: array())
*/
public function __construct($baseDir, array $options = array()) {
$this->baseDir = rtrim(realpath($baseDir), '/');
/**
* Mustache filesystem Loader constructor.
*
* Passing an $options array allows overriding certain Loader options during instantiation:
*
* $options = array(
* // The filename extension used for Mustache templates. Defaults to '.mustache'
* 'extension' => '.ms',
* );
*
* @throws RuntimeException if $baseDir does not exist.
*
* @param string $baseDir Base directory containing Mustache template files.
* @param array $options Array of Loader options (default: array())
*/
public function __construct($baseDir, array $options = array())
{
$this->baseDir = rtrim(realpath($baseDir), '/');
if (!is_dir($this->baseDir)) {
throw new RuntimeException('FilesystemLoader baseDir must be a directory: '.$baseDir);
}
if (!is_dir($this->baseDir)) {
throw new RuntimeException('FilesystemLoader baseDir must be a directory: '.$baseDir);
}
if (isset($options['extension'])) {
$this->extension = '.' . ltrim($options['extension'], '.');
}
}
if (isset($options['extension'])) {
$this->extension = '.' . ltrim($options['extension'], '.');
}
}
/**
* Load a Template by name.
*
* $loader = new FilesystemLoader(dirname(__FILE__).'/views');
* $loader->load('admin/dashboard'); // loads "./views/admin/dashboard.mustache";
*
* @param string $name
*
* @return string Mustache Template source
*/
public function load($name) {
if (!isset($this->templates[$name])) {
$this->templates[$name] = $this->loadFile($name);
}
/**
* Load a Template by name.
*
* $loader = new FilesystemLoader(dirname(__FILE__).'/views');
* $loader->load('admin/dashboard'); // loads "./views/admin/dashboard.mustache";
*
* @param string $name
*
* @return string Mustache Template source
*/
public function load($name)
{
if (!isset($this->templates[$name])) {
$this->templates[$name] = $this->loadFile($name);
}
return $this->templates[$name];
}
return $this->templates[$name];
}
/**
* Helper function for loading a Mustache file by name.
*
* @throws InvalidArgumentException if a template file is not found.
*
* @param string $name
*
* @return string Mustache Template source
*/
private function loadFile($name) {
$fileName = $this->getFileName($name);
/**
* Helper function for loading a Mustache file by name.
*
* @throws InvalidArgumentException if a template file is not found.
*
* @param string $name
*
* @return string Mustache Template source
*/
private function loadFile($name)
{
$fileName = $this->getFileName($name);
if (!file_exists($fileName)) {
throw new InvalidArgumentException('Template '.$name.' not found.');
}
if (!file_exists($fileName)) {
throw new InvalidArgumentException('Template '.$name.' not found.');
}
return file_get_contents($fileName);
}
return file_get_contents($fileName);
}
/**
* Helper function for getting a Mustache template file name.
*
* @param string $name
*
* @return string Template file name
*/
private function getFileName($name) {
$fileName = $this->baseDir . '/' . $name;
if (substr($fileName, 0 - strlen($this->extension)) !== $this->extension) {
$fileName .= $this->extension;
}
/**
* Helper function for getting a Mustache template file name.
*
* @param string $name
*
* @return string Template file name
*/
private function getFileName($name)
{
$fileName = $this->baseDir . '/' . $name;
if (substr($fileName, 0 - strlen($this->extension)) !== $this->extension) {
$fileName .= $this->extension;
}
return $fileName;
}
return $fileName;
}
}
+15 -14
View File
@@ -12,20 +12,21 @@
/**
* Mustache Template mutable Loader interface.
*/
interface Mustache_Loader_MutableLoader {
interface Mustache_Loader_MutableLoader
{
/**
* Set an associative array of Template sources for this loader.
*
* @param array $templates
*/
function setTemplates(array $templates);
/**
* Set an associative array of Template sources for this loader.
*
* @param array $templates
*/
public function setTemplates(array $templates);
/**
* Set a Template source by name.
*
* @param string $name
* @param string $template Mustache Template source
*/
function setTemplate($name, $template);
/**
* Set a Template source by name.
*
* @param string $name
* @param string $template Mustache Template source
*/
public function setTemplate($name, $template);
}
+13 -11
View File
@@ -25,16 +25,18 @@
*
* @implements Loader
*/
class Mustache_Loader_StringLoader implements Mustache_Loader {
class Mustache_Loader_StringLoader implements Mustache_Loader
{
/**
* Load a Template by source.
*
* @param string $name Mustache Template source
*
* @return string Mustache Template source
*/
public function load($name) {
return $name;
}
/**
* Load a Template by source.
*
* @param string $name Mustache Template source
*
* @return string Mustache Template source
*/
public function load($name)
{
return $name;
}
}
+59 -56
View File
@@ -14,72 +14,75 @@
*
* This class is responsible for turning a set of Mustache tokens into a parse tree.
*/
class Mustache_Parser {
class Mustache_Parser
{
/**
* Process an array of Mustache tokens and convert them into a parse tree.
*
* @param array $tokens Set of Mustache tokens
*
* @return array Mustache token parse tree
*/
public function parse(array $tokens = array()) {
return $this->buildTree(new ArrayIterator($tokens));
}
/**
* Process an array of Mustache tokens and convert them into a parse tree.
*
* @param array $tokens Set of Mustache tokens
*
* @return array Mustache token parse tree
*/
public function parse(array $tokens = array())
{
return $this->buildTree(new ArrayIterator($tokens));
}
/**
* Helper method for recursively building a parse tree.
*
* @throws LogicException when nesting errors or mismatched section tags are encountered.
*
* @param ArrayIterator $tokens Stream of Mustache tokens
* @param array $parent Parent token (default: null)
*
* @return array Mustache Token parse tree
*/
private function buildTree(ArrayIterator $tokens, array $parent = null) {
$nodes = array();
/**
* Helper method for recursively building a parse tree.
*
* @throws LogicException when nesting errors or mismatched section tags are encountered.
*
* @param ArrayIterator $tokens Stream of Mustache tokens
* @param array $parent Parent token (default: null)
*
* @return array Mustache Token parse tree
*/
private function buildTree(ArrayIterator $tokens, array $parent = null)
{
$nodes = array();
do {
$token = $tokens->current();
$tokens->next();
do {
$token = $tokens->current();
$tokens->next();
if ($token === null) {
continue;
} else {
switch ($token[Mustache_Tokenizer::TYPE]) {
case Mustache_Tokenizer::T_SECTION:
case Mustache_Tokenizer::T_INVERTED:
$nodes[] = $this->buildTree($tokens, $token);
break;
if ($token === null) {
continue;
} else {
switch ($token[Mustache_Tokenizer::TYPE]) {
case Mustache_Tokenizer::T_SECTION:
case Mustache_Tokenizer::T_INVERTED:
$nodes[] = $this->buildTree($tokens, $token);
break;
case Mustache_Tokenizer::T_END_SECTION:
if (!isset($parent)) {
throw new LogicException('Unexpected closing tag: /'. $token[Mustache_Tokenizer::NAME]);
}
case Mustache_Tokenizer::T_END_SECTION:
if (!isset($parent)) {
throw new LogicException('Unexpected closing tag: /'. $token[Mustache_Tokenizer::NAME]);
}
if ($token[Mustache_Tokenizer::NAME] !== $parent[Mustache_Tokenizer::NAME]) {
throw new LogicException('Nesting error: ' . $parent[Mustache_Tokenizer::NAME] . ' vs. ' . $token[Mustache_Tokenizer::NAME]);
}
if ($token[Mustache_Tokenizer::NAME] !== $parent[Mustache_Tokenizer::NAME]) {
throw new LogicException('Nesting error: ' . $parent[Mustache_Tokenizer::NAME] . ' vs. ' . $token[Mustache_Tokenizer::NAME]);
}
$parent[Mustache_Tokenizer::END] = $token[Mustache_Tokenizer::INDEX];
$parent[Mustache_Tokenizer::NODES] = $nodes;
$parent[Mustache_Tokenizer::END] = $token[Mustache_Tokenizer::INDEX];
$parent[Mustache_Tokenizer::NODES] = $nodes;
return $parent;
break;
return $parent;
break;
default:
$nodes[] = $token;
break;
}
}
default:
$nodes[] = $token;
break;
}
}
} while ($tokens->valid());
} while ($tokens->valid());
if (isset($parent)) {
throw new LogicException('Missing closing tag: ' . $parent[Mustache_Tokenizer::NAME]);
}
if (isset($parent)) {
throw new LogicException('Missing closing tag: ' . $parent[Mustache_Tokenizer::NAME]);
}
return $nodes;
}
return $nodes;
}
}
+121 -115
View File
@@ -14,130 +14,136 @@
*
* @abstract
*/
abstract class Mustache_Template {
abstract class Mustache_Template
{
/**
* @var Mustache_Engine
*/
protected $mustache;
/**
* @var Mustache_Engine
*/
protected $mustache;
/**
* Mustache Template constructor.
*
* @param Mustache_Engine $mustache
*/
public function __construct(Mustache_Engine $mustache) {
$this->mustache = $mustache;
}
/**
* Mustache Template constructor.
*
* @param Mustache_Engine $mustache
*/
public function __construct(Mustache_Engine $mustache)
{
$this->mustache = $mustache;
}
/**
* Mustache Template instances can be treated as a function and rendered by simply calling them:
*
* $m = new Mustache_Engine;
* $tpl = $m->loadTemplate('Hello, {{ name }}!');
* echo $tpl(array('name' => 'World')); // "Hello, World!"
*
* @see Mustache_Template::render
*
* @param mixed $context Array or object rendering context (default: array())
*
* @return string Rendered template
*/
public function __invoke($context = array()) {
return $this->render($context);
}
/**
* Mustache Template instances can be treated as a function and rendered by simply calling them:
*
* $m = new Mustache_Engine;
* $tpl = $m->loadTemplate('Hello, {{ name }}!');
* echo $tpl(array('name' => 'World')); // "Hello, World!"
*
* @see Mustache_Template::render
*
* @param mixed $context Array or object rendering context (default: array())
*
* @return string Rendered template
*/
public function __invoke($context = array())
{
return $this->render($context);
}
/**
* Render this template given the rendering context.
*
* @param mixed $context Array or object rendering context (default: array())
*
* @return string Rendered template
*/
public function render($context = array()) {
return $this->renderInternal($this->prepareContextStack($context));
}
/**
* Render this template given the rendering context.
*
* @param mixed $context Array or object rendering context (default: array())
*
* @return string Rendered template
*/
public function render($context = array())
{
return $this->renderInternal($this->prepareContextStack($context));
}
/**
* Internal rendering method implemented by Mustache Template concrete subclasses.
*
* This is where the magic happens :)
*
* @abstract
*
* @param Mustache_Context $context
*
* @return string Rendered template
*/
abstract public function renderInternal(Mustache_Context $context, $indent = '', $escape = false);
/**
* Internal rendering method implemented by Mustache Template concrete subclasses.
*
* This is where the magic happens :)
*
* @abstract
*
* @param Mustache_Context $context
*
* @return string Rendered template
*/
abstract public function renderInternal(Mustache_Context $context, $indent = '', $escape = false);
/**
* Tests whether a value should be iterated over (e.g. in a section context).
*
* In most languages there are two distinct array types: list and hash (or whatever you want to call them). Lists
* should be iterated, hashes should be treated as objects. Mustache follows this paradigm for Ruby, Javascript,
* Java, Python, etc.
*
* PHP, however, treats lists and hashes as one primitive type: array. So Mustache.php needs a way to distinguish
* between between a list of things (numeric, normalized array) and a set of variables to be used as section context
* (associative array). In other words, this will be iterated over:
*
* $items = array(
* array('name' => 'foo'),
* array('name' => 'bar'),
* array('name' => 'baz'),
* );
*
* ... but this will be used as a section context block:
*
* $items = array(
* 1 => array('name' => 'foo'),
* 'banana' => array('name' => 'bar'),
* 42 => array('name' => 'baz'),
* );
*
* @param mixed $value
*
* @return boolean True if the value is 'iterable'
*/
protected function isIterable($value) {
if (is_object($value)) {
return $value instanceof Traversable;
} elseif (is_array($value)) {
$i = 0;
foreach ($value as $k => $v) {
if ($k !== $i++) {
return false;
}
}
/**
* Tests whether a value should be iterated over (e.g. in a section context).
*
* In most languages there are two distinct array types: list and hash (or whatever you want to call them). Lists
* should be iterated, hashes should be treated as objects. Mustache follows this paradigm for Ruby, Javascript,
* Java, Python, etc.
*
* PHP, however, treats lists and hashes as one primitive type: array. So Mustache.php needs a way to distinguish
* between between a list of things (numeric, normalized array) and a set of variables to be used as section context
* (associative array). In other words, this will be iterated over:
*
* $items = array(
* array('name' => 'foo'),
* array('name' => 'bar'),
* array('name' => 'baz'),
* );
*
* ... but this will be used as a section context block:
*
* $items = array(
* 1 => array('name' => 'foo'),
* 'banana' => array('name' => 'bar'),
* 42 => array('name' => 'baz'),
* );
*
* @param mixed $value
*
* @return boolean True if the value is 'iterable'
*/
protected function isIterable($value)
{
if (is_object($value)) {
return $value instanceof Traversable;
} elseif (is_array($value)) {
$i = 0;
foreach ($value as $k => $v) {
if ($k !== $i++) {
return false;
}
}
return true;
} else {
return false;
}
}
return true;
} else {
return false;
}
}
/**
* Helper method to prepare the Context stack.
*
* Adds the Mustache HelperCollection to the stack's top context frame if helpers are present.
*
* @param mixed $context Optional first context frame (default: null)
*
* @return Mustache_Context
*/
protected function prepareContextStack($context = null) {
$stack = new Mustache_Context;
/**
* Helper method to prepare the Context stack.
*
* Adds the Mustache HelperCollection to the stack's top context frame if helpers are present.
*
* @param mixed $context Optional first context frame (default: null)
*
* @return Mustache_Context
*/
protected function prepareContextStack($context = null)
{
$stack = new Mustache_Context;
$helpers = $this->mustache->getHelpers();
if (!$helpers->isEmpty()) {
$stack->push($helpers);
}
$helpers = $this->mustache->getHelpers();
if (!$helpers->isEmpty()) {
$stack->push($helpers);
}
if (!empty($context)) {
$stack->push($context);
}
if (!empty($context)) {
$stack->push($context);
}
return $stack;
}
return $stack;
}
}
+240 -233
View File
@@ -16,263 +16,270 @@
*/
class Mustache_Tokenizer {
// Finite state machine states
const IN_TEXT = 0;
const IN_TAG_TYPE = 1;
const IN_TAG = 2;
// Finite state machine states
const IN_TEXT = 0;
const IN_TAG_TYPE = 1;
const IN_TAG = 2;
// Token types
const T_SECTION = '#';
const T_INVERTED = '^';
const T_END_SECTION = '/';
const T_COMMENT = '!';
const T_PARTIAL = '>';
const T_PARTIAL_2 = '<';
const T_DELIM_CHANGE = '=';
const T_ESCAPED = '_v';
const T_UNESCAPED = '{';
const T_UNESCAPED_2 = '&';
const T_TEXT = '_t';
// Token types
const T_SECTION = '#';
const T_INVERTED = '^';
const T_END_SECTION = '/';
const T_COMMENT = '!';
const T_PARTIAL = '>';
const T_PARTIAL_2 = '<';
const T_DELIM_CHANGE = '=';
const T_ESCAPED = '_v';
const T_UNESCAPED = '{';
const T_UNESCAPED_2 = '&';
const T_TEXT = '_t';
// Valid token types
private static $tagTypes = array(
self::T_SECTION => true,
self::T_INVERTED => true,
self::T_END_SECTION => true,
self::T_COMMENT => true,
self::T_PARTIAL => true,
self::T_PARTIAL_2 => true,
self::T_DELIM_CHANGE => true,
self::T_ESCAPED => true,
self::T_UNESCAPED => true,
self::T_UNESCAPED_2 => true,
);
// Valid token types
private static $tagTypes = array(
self::T_SECTION => true,
self::T_INVERTED => true,
self::T_END_SECTION => true,
self::T_COMMENT => true,
self::T_PARTIAL => true,
self::T_PARTIAL_2 => true,
self::T_DELIM_CHANGE => true,
self::T_ESCAPED => true,
self::T_UNESCAPED => true,
self::T_UNESCAPED_2 => true,
);
// Interpolated tags
private static $interpolatedTags = array(
self::T_ESCAPED => true,
self::T_UNESCAPED => true,
self::T_UNESCAPED_2 => true,
);
// Interpolated tags
private static $interpolatedTags = array(
self::T_ESCAPED => true,
self::T_UNESCAPED => true,
self::T_UNESCAPED_2 => true,
);
// Token properties
const TYPE = 'type';
const NAME = 'name';
const OTAG = 'otag';
const CTAG = 'ctag';
const INDEX = 'index';
const END = 'end';
const INDENT = 'indent';
const NODES = 'nodes';
const VALUE = 'value';
// Token properties
const TYPE = 'type';
const NAME = 'name';
const OTAG = 'otag';
const CTAG = 'ctag';
const INDEX = 'index';
const END = 'end';
const INDENT = 'indent';
const NODES = 'nodes';
const VALUE = 'value';
private $state;
private $tagType;
private $tag;
private $buffer;
private $tokens;
private $seenTag;
private $lineStart;
private $otag;
private $ctag;
private $state;
private $tagType;
private $tag;
private $buffer;
private $tokens;
private $seenTag;
private $lineStart;
private $otag;
private $ctag;
/**
* Scan and tokenize template source.
*
* @param string $text Mustache template source to tokenize
* @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null)
*
* @return array Set of Mustache tokens
*/
public function scan($text, $delimiters = null) {
$this->reset();
/**
* Scan and tokenize template source.
*
* @param string $text Mustache template source to tokenize
* @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null)
*
* @return array Set of Mustache tokens
*/
public function scan($text, $delimiters = null)
{
$this->reset();
if ($delimiters = trim($delimiters)) {
list($otag, $ctag) = explode(' ', $delimiters);
$this->otag = $otag;
$this->ctag = $ctag;
}
if ($delimiters = trim($delimiters)) {
list($otag, $ctag) = explode(' ', $delimiters);
$this->otag = $otag;
$this->ctag = $ctag;
}
$len = strlen($text);
for ($i = 0; $i < $len; $i++) {
switch ($this->state) {
case self::IN_TEXT:
if ($this->tagChange($this->otag, $text, $i)) {
$i--;
$this->flushBuffer();
$this->state = self::IN_TAG_TYPE;
} else {
if ($text[$i] == "\n") {
$this->filterLine();
} else {
$this->buffer .= $text[$i];
}
}
break;
$len = strlen($text);
for ($i = 0; $i < $len; $i++) {
switch ($this->state) {
case self::IN_TEXT:
if ($this->tagChange($this->otag, $text, $i)) {
$i--;
$this->flushBuffer();
$this->state = self::IN_TAG_TYPE;
} else {
if ($text[$i] == "\n") {
$this->filterLine();
} else {
$this->buffer .= $text[$i];
}
}
break;
case self::IN_TAG_TYPE:
case self::IN_TAG_TYPE:
$i += strlen($this->otag) - 1;
if (isset(self::$tagTypes[$text[$i + 1]])) {
$tag = $text[$i + 1];
$this->tagType = $tag;
} else {
$tag = null;
$this->tagType = self::T_ESCAPED;
}
$i += strlen($this->otag) - 1;
if (isset(self::$tagTypes[$text[$i + 1]])) {
$tag = $text[$i + 1];
$this->tagType = $tag;
} else {
$tag = null;
$this->tagType = self::T_ESCAPED;
}
if ($this->tagType === self::T_DELIM_CHANGE) {
$i = $this->changeDelimiters($text, $i);
$this->state = self::IN_TEXT;
} else {
if ($tag !== null) {
$i++;
}
$this->state = self::IN_TAG;
}
$this->seenTag = $i;
break;
if ($this->tagType === self::T_DELIM_CHANGE) {
$i = $this->changeDelimiters($text, $i);
$this->state = self::IN_TEXT;
} else {
if ($tag !== null) {
$i++;
}
$this->state = self::IN_TAG;
}
$this->seenTag = $i;
break;
default:
if ($this->tagChange($this->ctag, $text, $i)) {
$this->tokens[] = array(
self::TYPE => $this->tagType,
self::NAME => trim($this->buffer),
self::OTAG => $this->otag,
self::CTAG => $this->ctag,
self::INDEX => ($this->tagType == self::T_END_SECTION) ? $this->seenTag - strlen($this->otag) : $i + strlen($this->ctag)
);
default:
if ($this->tagChange($this->ctag, $text, $i)) {
$this->tokens[] = array(
self::TYPE => $this->tagType,
self::NAME => trim($this->buffer),
self::OTAG => $this->otag,
self::CTAG => $this->ctag,
self::INDEX => ($this->tagType == self::T_END_SECTION) ? $this->seenTag - strlen($this->otag) : $i + strlen($this->ctag)
);
$this->buffer = '';
$i += strlen($this->ctag) - 1;
$this->state = self::IN_TEXT;
if ($this->tagType == self::T_UNESCAPED) {
if ($this->ctag == '}}') {
$i++;
} else {
// Clean up `{{{ tripleStache }}}` style tokens.
$lastName = $this->tokens[count($this->tokens) - 1][self::NAME];
if (substr($lastName, -1) === '}') {
$this->tokens[count($this->tokens) - 1][self::NAME] = trim(substr($lastName, 0, -1));
}
}
}
} else {
$this->buffer .= $text[$i];
}
break;
}
}
$this->buffer = '';
$i += strlen($this->ctag) - 1;
$this->state = self::IN_TEXT;
if ($this->tagType == self::T_UNESCAPED) {
if ($this->ctag == '}}') {
$i++;
} else {
// Clean up `{{{ tripleStache }}}` style tokens.
$lastName = $this->tokens[count($this->tokens) - 1][self::NAME];
if (substr($lastName, -1) === '}') {
$this->tokens[count($this->tokens) - 1][self::NAME] = trim(substr($lastName, 0, -1));
}
}
}
} else {
$this->buffer .= $text[$i];
}
break;
}
}
$this->filterLine(true);
$this->filterLine(true);
return $this->tokens;
}
return $this->tokens;
}
/**
* Helper function to reset tokenizer internal state.
*/
private function reset() {
$this->state = self::IN_TEXT;
$this->tagType = null;
$this->tag = null;
$this->buffer = '';
$this->tokens = array();
$this->seenTag = false;
$this->lineStart = 0;
$this->otag = '{{';
$this->ctag = '}}';
}
/**
* Helper function to reset tokenizer internal state.
*/
private function reset()
{
$this->state = self::IN_TEXT;
$this->tagType = null;
$this->tag = null;
$this->buffer = '';
$this->tokens = array();
$this->seenTag = false;
$this->lineStart = 0;
$this->otag = '{{';
$this->ctag = '}}';
}
/**
* Flush the current buffer to a token.
*/
private function flushBuffer() {
if (!empty($this->buffer)) {
$this->tokens[] = array(self::TYPE => self::T_TEXT, self::VALUE => $this->buffer);
$this->buffer = '';
}
}
/**
* Flush the current buffer to a token.
*/
private function flushBuffer()
{
if (!empty($this->buffer)) {
$this->tokens[] = array(self::TYPE => self::T_TEXT, self::VALUE => $this->buffer);
$this->buffer = '';
}
}
/**
* Test whether the current line is entirely made up of whitespace.
*
* @return boolean True if the current line is all whitespace
*/
private function lineIsWhitespace() {
$tokensCount = count($this->tokens);
for ($j = $this->lineStart; $j < $tokensCount; $j++) {
$token = $this->tokens[$j];
if (isset(self::$tagTypes[$token[self::TYPE]])) {
if (isset(self::$interpolatedTags[$token[self::TYPE]])) {
return false;
}
} elseif ($token[self::TYPE] == self::T_TEXT) {
if (preg_match('/\S/', $token[self::VALUE])) {
return false;
}
}
}
/**
* Test whether the current line is entirely made up of whitespace.
*
* @return boolean True if the current line is all whitespace
*/
private function lineIsWhitespace()
{
$tokensCount = count($this->tokens);
for ($j = $this->lineStart; $j < $tokensCount; $j++) {
$token = $this->tokens[$j];
if (isset(self::$tagTypes[$token[self::TYPE]])) {
if (isset(self::$interpolatedTags[$token[self::TYPE]])) {
return false;
}
} elseif ($token[self::TYPE] == self::T_TEXT) {
if (preg_match('/\S/', $token[self::VALUE])) {
return false;
}
}
}
return true;
}
return true;
}
/**
* Filter out whitespace-only lines and store indent levels for partials.
*
* @param bool $noNewLine Suppress the newline? (default: false)
*/
private function filterLine($noNewLine = false) {
$this->flushBuffer();
if ($this->seenTag && $this->lineIsWhitespace()) {
$tokensCount = count($this->tokens);
for ($j = $this->lineStart; $j < $tokensCount; $j++) {
if ($this->tokens[$j][self::TYPE] == self::T_TEXT) {
if (isset($this->tokens[$j+1]) && $this->tokens[$j+1][self::TYPE] == self::T_PARTIAL) {
$this->tokens[$j+1][self::INDENT] = $this->tokens[$j][self::VALUE];
}
/**
* Filter out whitespace-only lines and store indent levels for partials.
*
* @param bool $noNewLine Suppress the newline? (default: false)
*/
private function filterLine($noNewLine = false)
{
$this->flushBuffer();
if ($this->seenTag && $this->lineIsWhitespace()) {
$tokensCount = count($this->tokens);
for ($j = $this->lineStart; $j < $tokensCount; $j++) {
if ($this->tokens[$j][self::TYPE] == self::T_TEXT) {
if (isset($this->tokens[$j+1]) && $this->tokens[$j+1][self::TYPE] == self::T_PARTIAL) {
$this->tokens[$j+1][self::INDENT] = $this->tokens[$j][self::VALUE];
}
$this->tokens[$j] = null;
}
}
} elseif (!$noNewLine) {
$this->tokens[] = array(self::TYPE => self::T_TEXT, self::VALUE => "\n");
}
$this->tokens[$j] = null;
}
}
} elseif (!$noNewLine) {
$this->tokens[] = array(self::TYPE => self::T_TEXT, self::VALUE => "\n");
}
$this->seenTag = false;
$this->lineStart = count($this->tokens);
}
$this->seenTag = false;
$this->lineStart = count($this->tokens);
}
/**
* Change the current Mustache delimiters. Set new `otag` and `ctag` values.
*
* @param string $text Mustache template source
* @param int $index Current tokenizer index
*
* @return int New index value
*/
private function changeDelimiters($text, $index) {
$startIndex = strpos($text, '=', $index) + 1;
$close = '='.$this->ctag;
$closeIndex = strpos($text, $close, $index);
/**
* Change the current Mustache delimiters. Set new `otag` and `ctag` values.
*
* @param string $text Mustache template source
* @param int $index Current tokenizer index
*
* @return int New index value
*/
private function changeDelimiters($text, $index)
{
$startIndex = strpos($text, '=', $index) + 1;
$close = '='.$this->ctag;
$closeIndex = strpos($text, $close, $index);
list($otag, $ctag) = explode(' ', trim(substr($text, $startIndex, $closeIndex - $startIndex)));
$this->otag = $otag;
$this->ctag = $ctag;
list($otag, $ctag) = explode(' ', trim(substr($text, $startIndex, $closeIndex - $startIndex)));
$this->otag = $otag;
$this->ctag = $ctag;
return $closeIndex + strlen($close) - 1;
}
return $closeIndex + strlen($close) - 1;
}
/**
* Test whether it's time to change tags.
*
* @param string $tag Current tag name
* @param string $text Mustache template source
* @param int $index Current tokenizer index
*
* @return boolean True if this is a closing section tag
*/
private function tagChange($tag, $text, $index) {
return substr($text, $index, strlen($tag)) === $tag;
}
/**
* Test whether it's time to change tags.
*
* @param string $tag Current tag name
* @param string $text Mustache template source
* @param int $index Current tokenizer index
*
* @return boolean True if this is a closing section tag
*/
private function tagChange($tag, $text, $index)
{
return substr($text, $index, strlen($tag)) === $tag;
}
}
+17 -14
View File
@@ -12,22 +12,25 @@
/**
* @group unit
*/
class Mustache_Test_AutoloaderTest extends PHPUnit_Framework_TestCase {
public function testRegister() {
$loader = Mustache_Autoloader::register();
$this->assertTrue(spl_autoload_unregister(array($loader, 'autoload')));
}
class Mustache_Test_AutoloaderTest extends PHPUnit_Framework_TestCase
{
public function testRegister()
{
$loader = Mustache_Autoloader::register();
$this->assertTrue(spl_autoload_unregister(array($loader, 'autoload')));
}
public function testAutoloader() {
$loader = new Mustache_Autoloader(dirname(__FILE__).'/../../fixtures/autoloader');
public function testAutoloader()
{
$loader = new Mustache_Autoloader(dirname(__FILE__).'/../../fixtures/autoloader');
$this->assertNull($loader->autoload('NonMustacheClass'));
$this->assertFalse(class_exists('NonMustacheClass'));
$this->assertNull($loader->autoload('NonMustacheClass'));
$this->assertFalse(class_exists('NonMustacheClass'));
$loader->autoload('Mustache_Foo');
$this->assertTrue(class_exists('Mustache_Foo'));
$loader->autoload('Mustache_Foo');
$this->assertTrue(class_exists('Mustache_Foo'));
$loader->autoload('\Mustache_Bar');
$this->assertTrue(class_exists('Mustache_Bar'));
}
$loader->autoload('\Mustache_Bar');
$this->assertTrue(class_exists('Mustache_Bar'));
}
}
+80 -75
View File
@@ -12,87 +12,92 @@
/**
* @group unit
*/
class Mustache_Test_CompilerTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_CompilerTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider getCompileValues
*/
public function testCompile($source, array $tree, $name, $customEscaper, $charset, $expected) {
$compiler = new Mustache_Compiler;
/**
* @dataProvider getCompileValues
*/
public function testCompile($source, array $tree, $name, $customEscaper, $charset, $expected)
{
$compiler = new Mustache_Compiler;
$compiled = $compiler->compile($source, $tree, $name, $customEscaper, $charset);
foreach ($expected as $contains) {
$this->assertContains($contains, $compiled);
}
}
$compiled = $compiler->compile($source, $tree, $name, $customEscaper, $charset);
foreach ($expected as $contains) {
$this->assertContains($contains, $compiled);
}
}
public function getCompileValues() {
return array(
array('', array(), 'Banana', false, 'ISO-8859-1', array(
"\nclass Banana extends Mustache_Template",
'return htmlspecialchars($buffer, ENT_COMPAT, \'ISO-8859-1\');',
'return $buffer;',
)),
public function getCompileValues()
{
return array(
array('', array(), 'Banana', false, 'ISO-8859-1', array(
"\nclass Banana extends Mustache_Template",
'return htmlspecialchars($buffer, ENT_COMPAT, \'ISO-8859-1\');',
'return $buffer;',
)),
array('', array($this->createTextToken('TEXT')), 'Monkey', false, 'UTF-8', array(
"\nclass Monkey extends Mustache_Template",
'return htmlspecialchars($buffer, ENT_COMPAT, \'UTF-8\');',
'$buffer .= $indent . \'TEXT\';',
'return $buffer;',
)),
array('', array($this->createTextToken('TEXT')), 'Monkey', false, 'UTF-8', array(
"\nclass Monkey extends Mustache_Template",
'return htmlspecialchars($buffer, ENT_COMPAT, \'UTF-8\');',
'$buffer .= $indent . \'TEXT\';',
'return $buffer;',
)),
array('', array($this->createTextToken('TEXT')), 'Monkey', true, 'ISO-8859-1', array(
"\nclass Monkey extends Mustache_Template",
'$buffer .= $indent . \'TEXT\';',
'return call_user_func($this->mustache->getEscape(), $buffer);',
'return $buffer;',
)),
array('', array($this->createTextToken('TEXT')), 'Monkey', true, 'ISO-8859-1', array(
"\nclass Monkey extends Mustache_Template",
'$buffer .= $indent . \'TEXT\';',
'return call_user_func($this->mustache->getEscape(), $buffer);',
'return $buffer;',
)),
array(
'',
array(
$this->createTextToken('foo'),
$this->createTextToken("\n"),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name',
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => '.',
),
$this->createTextToken("'bar'"),
),
'Monkey',
false,
'UTF-8',
array(
"\nclass Monkey extends Mustache_Template",
'$buffer .= $indent . \'foo\'',
'$buffer .= "\n"',
'$value = $context->find(\'name\');',
'$buffer .= htmlspecialchars($value, ENT_COMPAT, \'UTF-8\');',
'$value = $context->last();',
'$buffer .= \'\\\'bar\\\'\';',
'return htmlspecialchars($buffer, ENT_COMPAT, \'UTF-8\');',
'return $buffer;',
)
),
);
}
array(
'',
array(
$this->createTextToken('foo'),
$this->createTextToken("\n"),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name',
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => '.',
),
$this->createTextToken("'bar'"),
),
'Monkey',
false,
'UTF-8',
array(
"\nclass Monkey extends Mustache_Template",
'$buffer .= $indent . \'foo\'',
'$buffer .= "\n"',
'$value = $context->find(\'name\');',
'$buffer .= htmlspecialchars($value, ENT_COMPAT, \'UTF-8\');',
'$value = $context->last();',
'$buffer .= \'\\\'bar\\\'\';',
'return htmlspecialchars($buffer, ENT_COMPAT, \'UTF-8\');',
'return $buffer;',
)
),
);
}
/**
* @expectedException InvalidArgumentException
*/
public function testCompilerThrowsUnknownNodeTypeException() {
$compiler = new Mustache_Compiler;
$compiler->compile('', array(array(Mustache_Tokenizer::TYPE => 'invalid')), 'SomeClass');
}
/**
* @expectedException InvalidArgumentException
*/
public function testCompilerThrowsUnknownNodeTypeException()
{
$compiler = new Mustache_Compiler;
$compiler->compile('', array(array(Mustache_Tokenizer::TYPE => 'invalid')), 'SomeClass');
}
private function createTextToken($value) {
return array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => $value,
);
}
private function createTextToken($value)
{
return array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => $value,
);
}
}
+82 -74
View File
@@ -12,100 +12,108 @@
/**
* @group unit
*/
class Mustache_Test_ContextTest extends PHPUnit_Framework_TestCase {
public function testConstructor() {
$one = new Mustache_Context;
$this->assertSame('', $one->find('foo'));
$this->assertSame('', $one->find('bar'));
class Mustache_Test_ContextTest extends PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$one = new Mustache_Context;
$this->assertSame('', $one->find('foo'));
$this->assertSame('', $one->find('bar'));
$two = new Mustache_Context(array(
'foo' => 'FOO',
'bar' => '<BAR>'
));
$this->assertEquals('FOO', $two->find('foo'));
$this->assertEquals('<BAR>', $two->find('bar'));
$two = new Mustache_Context(array(
'foo' => 'FOO',
'bar' => '<BAR>'
));
$this->assertEquals('FOO', $two->find('foo'));
$this->assertEquals('<BAR>', $two->find('bar'));
$obj = new StdClass;
$obj->name = 'NAME';
$three = new Mustache_Context($obj);
$this->assertSame($obj, $three->last());
$this->assertEquals('NAME', $three->find('name'));
}
$obj = new StdClass;
$obj->name = 'NAME';
$three = new Mustache_Context($obj);
$this->assertSame($obj, $three->last());
$this->assertEquals('NAME', $three->find('name'));
}
public function testPushPopAndLast() {
$context = new Mustache_Context;
$this->assertFalse($context->last());
public function testPushPopAndLast()
{
$context = new Mustache_Context;
$this->assertFalse($context->last());
$dummy = new Mustache_Test_TestDummy;
$context->push($dummy);
$this->assertSame($dummy, $context->last());
$this->assertSame($dummy, $context->pop());
$this->assertFalse($context->last());
$dummy = new Mustache_Test_TestDummy;
$context->push($dummy);
$this->assertSame($dummy, $context->last());
$this->assertSame($dummy, $context->pop());
$this->assertFalse($context->last());
$obj = new StdClass;
$context->push($dummy);
$this->assertSame($dummy, $context->last());
$context->push($obj);
$this->assertSame($obj, $context->last());
$this->assertSame($obj, $context->pop());
$this->assertSame($dummy, $context->pop());
$this->assertFalse($context->last());
}
$obj = new StdClass;
$context->push($dummy);
$this->assertSame($dummy, $context->last());
$context->push($obj);
$this->assertSame($obj, $context->last());
$this->assertSame($obj, $context->pop());
$this->assertSame($dummy, $context->pop());
$this->assertFalse($context->last());
}
public function testFind() {
$context = new Mustache_Context;
public function testFind()
{
$context = new Mustache_Context;
$dummy = new Mustache_Test_TestDummy;
$dummy = new Mustache_Test_TestDummy;
$obj = new StdClass;
$obj->name = 'obj';
$obj = new StdClass;
$obj->name = 'obj';
$arr = array(
'a' => array('b' => array('c' => 'see')),
'b' => 'bee',
);
$arr = array(
'a' => array('b' => array('c' => 'see')),
'b' => 'bee',
);
$string = 'some arbitrary string';
$string = 'some arbitrary string';
$context->push($dummy);
$this->assertEquals('dummy', $context->find('name'));
$context->push($dummy);
$this->assertEquals('dummy', $context->find('name'));
$context->push($obj);
$this->assertEquals('obj', $context->find('name'));
$context->push($obj);
$this->assertEquals('obj', $context->find('name'));
$context->pop();
$this->assertEquals('dummy', $context->find('name'));
$context->pop();
$this->assertEquals('dummy', $context->find('name'));
$dummy->name = 'dummyer';
$this->assertEquals('dummyer', $context->find('name'));
$dummy->name = 'dummyer';
$this->assertEquals('dummyer', $context->find('name'));
$context->push($arr);
$this->assertEquals('bee', $context->find('b'));
$this->assertEquals('see', $context->findDot('a.b.c'));
$context->push($arr);
$this->assertEquals('bee', $context->find('b'));
$this->assertEquals('see', $context->findDot('a.b.c'));
$dummy->name = 'dummy';
$dummy->name = 'dummy';
$context->push($string);
$this->assertSame($string, $context->last());
$this->assertEquals('dummy', $context->find('name'));
$this->assertEquals('see', $context->findDot('a.b.c'));
$this->assertEquals('<foo>', $context->find('foo'));
$this->assertEquals('<bar>', $context->findDot('bar'));
}
$context->push($string);
$this->assertSame($string, $context->last());
$this->assertEquals('dummy', $context->find('name'));
$this->assertEquals('see', $context->findDot('a.b.c'));
$this->assertEquals('<foo>', $context->find('foo'));
$this->assertEquals('<bar>', $context->findDot('bar'));
}
}
class Mustache_Test_TestDummy {
public $name = 'dummy';
class Mustache_Test_TestDummy
{
public $name = 'dummy';
public function __invoke() {
// nothing
}
public function __invoke()
{
// nothing
}
public static function foo() {
return '<foo>';
}
public static function foo()
{
return '<foo>';
}
public function bar() {
return '<bar>';
}
public function bar()
{
return '<bar>';
}
}
+202 -186
View File
@@ -12,229 +12,245 @@
/**
* @group unit
*/
class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase
{
private static $tempDir;
private static $tempDir;
public static function setUpBeforeClass() {
self::$tempDir = sys_get_temp_dir() . '/mustache_test';
if (file_exists(self::$tempDir)) {
self::rmdir(self::$tempDir);
}
}
public static function setUpBeforeClass()
{
self::$tempDir = sys_get_temp_dir() . '/mustache_test';
if (file_exists(self::$tempDir)) {
self::rmdir(self::$tempDir);
}
}
public function testConstructor() {
$loader = new Mustache_Loader_StringLoader;
$partialsLoader = new Mustache_Loader_ArrayLoader;
$mustache = new Mustache_Engine(array(
'template_class_prefix' => '__whot__',
'cache' => self::$tempDir,
'loader' => $loader,
'partials_loader' => $partialsLoader,
'partials' => array(
'foo' => '{{ foo }}',
),
'helpers' => array(
'foo' => array($this, 'getFoo'),
'bar' => 'BAR',
),
'escape' => 'strtoupper',
'charset' => 'ISO-8859-1',
));
public function testConstructor()
{
$loader = new Mustache_Loader_StringLoader;
$partialsLoader = new Mustache_Loader_ArrayLoader;
$mustache = new Mustache_Engine(array(
'template_class_prefix' => '__whot__',
'cache' => self::$tempDir,
'loader' => $loader,
'partials_loader' => $partialsLoader,
'partials' => array(
'foo' => '{{ foo }}',
),
'helpers' => array(
'foo' => array($this, 'getFoo'),
'bar' => 'BAR',
),
'escape' => 'strtoupper',
'charset' => 'ISO-8859-1',
));
$this->assertSame($loader, $mustache->getLoader());
$this->assertSame($partialsLoader, $mustache->getPartialsLoader());
$this->assertEquals('{{ foo }}', $partialsLoader->load('foo'));
$this->assertContains('__whot__', $mustache->getTemplateClassName('{{ foo }}'));
$this->assertEquals('strtoupper', $mustache->getEscape());
$this->assertEquals('ISO-8859-1', $mustache->getCharset());
$this->assertTrue($mustache->hasHelper('foo'));
$this->assertTrue($mustache->hasHelper('bar'));
$this->assertFalse($mustache->hasHelper('baz'));
}
$this->assertSame($loader, $mustache->getLoader());
$this->assertSame($partialsLoader, $mustache->getPartialsLoader());
$this->assertEquals('{{ foo }}', $partialsLoader->load('foo'));
$this->assertContains('__whot__', $mustache->getTemplateClassName('{{ foo }}'));
$this->assertEquals('strtoupper', $mustache->getEscape());
$this->assertEquals('ISO-8859-1', $mustache->getCharset());
$this->assertTrue($mustache->hasHelper('foo'));
$this->assertTrue($mustache->hasHelper('bar'));
$this->assertFalse($mustache->hasHelper('baz'));
}
public static function getFoo() {
return 'foo';
}
public static function getFoo()
{
return 'foo';
}
public function testRender() {
$source = '{{ foo }}';
$data = array('bar' => 'baz');
$output = 'TEH OUTPUT';
public function testRender()
{
$source = '{{ foo }}';
$data = array('bar' => 'baz');
$output = 'TEH OUTPUT';
$template = $this->getMockBuilder('Mustache_Template')
->disableOriginalConstructor()
->getMock();
$template = $this->getMockBuilder('Mustache_Template')
->disableOriginalConstructor()
->getMock();
$mustache = new MustacheStub;
$mustache->template = $template;
$mustache = new MustacheStub;
$mustache->template = $template;
$template->expects($this->once())
->method('render')
->with($data)
->will($this->returnValue($output));
$template->expects($this->once())
->method('render')
->with($data)
->will($this->returnValue($output));
$this->assertEquals($output, $mustache->render($source, $data));
$this->assertEquals($source, $mustache->source);
}
$this->assertEquals($output, $mustache->render($source, $data));
$this->assertEquals($source, $mustache->source);
}
public function testSettingServices() {
$loader = new Mustache_Loader_StringLoader;
$tokenizer = new Mustache_Tokenizer;
$parser = new Mustache_Parser;
$compiler = new Mustache_Compiler;
$mustache = new Mustache_Engine;
public function testSettingServices()
{
$loader = new Mustache_Loader_StringLoader;
$tokenizer = new Mustache_Tokenizer;
$parser = new Mustache_Parser;
$compiler = new Mustache_Compiler;
$mustache = new Mustache_Engine;
$this->assertNotSame($loader, $mustache->getLoader());
$mustache->setLoader($loader);
$this->assertSame($loader, $mustache->getLoader());
$this->assertNotSame($loader, $mustache->getLoader());
$mustache->setLoader($loader);
$this->assertSame($loader, $mustache->getLoader());
$this->assertNotSame($loader, $mustache->getPartialsLoader());
$mustache->setPartialsLoader($loader);
$this->assertSame($loader, $mustache->getPartialsLoader());
$this->assertNotSame($loader, $mustache->getPartialsLoader());
$mustache->setPartialsLoader($loader);
$this->assertSame($loader, $mustache->getPartialsLoader());
$this->assertNotSame($tokenizer, $mustache->getTokenizer());
$mustache->setTokenizer($tokenizer);
$this->assertSame($tokenizer, $mustache->getTokenizer());
$this->assertNotSame($tokenizer, $mustache->getTokenizer());
$mustache->setTokenizer($tokenizer);
$this->assertSame($tokenizer, $mustache->getTokenizer());
$this->assertNotSame($parser, $mustache->getParser());
$mustache->setParser($parser);
$this->assertSame($parser, $mustache->getParser());
$this->assertNotSame($parser, $mustache->getParser());
$mustache->setParser($parser);
$this->assertSame($parser, $mustache->getParser());
$this->assertNotSame($compiler, $mustache->getCompiler());
$mustache->setCompiler($compiler);
$this->assertSame($compiler, $mustache->getCompiler());
}
$this->assertNotSame($compiler, $mustache->getCompiler());
$mustache->setCompiler($compiler);
$this->assertSame($compiler, $mustache->getCompiler());
}
/**
* @group functional
*/
public function testCache() {
$mustache = new Mustache_Engine(array(
'template_class_prefix' => '__whot__',
'cache' => self::$tempDir,
));
/**
* @group functional
*/
public function testCache()
{
$mustache = new Mustache_Engine(array(
'template_class_prefix' => '__whot__',
'cache' => self::$tempDir,
));
$source = '{{ foo }}';
$template = $mustache->loadTemplate($source);
$className = $mustache->getTemplateClassName($source);
$fileName = self::$tempDir . '/' . $className . '.php';
$this->assertInstanceOf($className, $template);
$this->assertFileExists($fileName);
$this->assertContains("\nclass $className extends Mustache_Template", file_get_contents($fileName));
}
$source = '{{ foo }}';
$template = $mustache->loadTemplate($source);
$className = $mustache->getTemplateClassName($source);
$fileName = self::$tempDir . '/' . $className . '.php';
$this->assertInstanceOf($className, $template);
$this->assertFileExists($fileName);
$this->assertContains("\nclass $className extends Mustache_Template", file_get_contents($fileName));
}
/**
* @expectedException InvalidArgumentException
* @dataProvider getBadEscapers
*/
public function testNonCallableEscapeThrowsException($escape) {
new Mustache_Engine(array('escape' => $escape));
}
/**
* @expectedException InvalidArgumentException
* @dataProvider getBadEscapers
*/
public function testNonCallableEscapeThrowsException($escape)
{
new Mustache_Engine(array('escape' => $escape));
}
public function getBadEscapers() {
return array(
array('nothing'),
array('foo', 'bar'),
);
}
public function getBadEscapers()
{
return array(
array('nothing'),
array('foo', 'bar'),
);
}
/**
* @expectedException RuntimeException
*/
public function testImmutablePartialsLoadersThrowException() {
$mustache = new Mustache_Engine(array(
'partials_loader' => new Mustache_Loader_StringLoader,
));
/**
* @expectedException RuntimeException
*/
public function testImmutablePartialsLoadersThrowException()
{
$mustache = new Mustache_Engine(array(
'partials_loader' => new Mustache_Loader_StringLoader,
));
$mustache->setPartials(array('foo' => '{{ foo }}'));
}
$mustache->setPartials(array('foo' => '{{ foo }}'));
}
public function testMissingPartialsTreatedAsEmptyString() {
$mustache = new Mustache_Engine(array(
'partials_loader' => new Mustache_Loader_ArrayLoader(array(
'foo' => 'FOO',
'baz' => 'BAZ',
))
));
public function testMissingPartialsTreatedAsEmptyString()
{
$mustache = new Mustache_Engine(array(
'partials_loader' => new Mustache_Loader_ArrayLoader(array(
'foo' => 'FOO',
'baz' => 'BAZ',
))
));
$this->assertEquals('FOOBAZ', $mustache->render('{{>foo}}{{>bar}}{{>baz}}', array()));
}
$this->assertEquals('FOOBAZ', $mustache->render('{{>foo}}{{>bar}}{{>baz}}', array()));
}
public function testHelpers() {
$foo = array($this, 'getFoo');
$bar = 'BAR';
$mustache = new Mustache_Engine(array('helpers' => array(
'foo' => $foo,
'bar' => $bar,
)));
public function testHelpers()
{
$foo = array($this, 'getFoo');
$bar = 'BAR';
$mustache = new Mustache_Engine(array('helpers' => array(
'foo' => $foo,
'bar' => $bar,
)));
$helpers = $mustache->getHelpers();
$this->assertTrue($mustache->hasHelper('foo'));
$this->assertTrue($mustache->hasHelper('bar'));
$this->assertTrue($helpers->has('foo'));
$this->assertTrue($helpers->has('bar'));
$this->assertSame($foo, $mustache->getHelper('foo'));
$this->assertSame($bar, $mustache->getHelper('bar'));
$helpers = $mustache->getHelpers();
$this->assertTrue($mustache->hasHelper('foo'));
$this->assertTrue($mustache->hasHelper('bar'));
$this->assertTrue($helpers->has('foo'));
$this->assertTrue($helpers->has('bar'));
$this->assertSame($foo, $mustache->getHelper('foo'));
$this->assertSame($bar, $mustache->getHelper('bar'));
$mustache->removeHelper('bar');
$this->assertFalse($mustache->hasHelper('bar'));
$mustache->addHelper('bar', $bar);
$this->assertSame($bar, $mustache->getHelper('bar'));
$mustache->removeHelper('bar');
$this->assertFalse($mustache->hasHelper('bar'));
$mustache->addHelper('bar', $bar);
$this->assertSame($bar, $mustache->getHelper('bar'));
$baz = array($this, 'wrapWithUnderscores');
$this->assertFalse($mustache->hasHelper('baz'));
$this->assertFalse($helpers->has('baz'));
$baz = array($this, 'wrapWithUnderscores');
$this->assertFalse($mustache->hasHelper('baz'));
$this->assertFalse($helpers->has('baz'));
$mustache->addHelper('baz', $baz);
$this->assertTrue($mustache->hasHelper('baz'));
$this->assertTrue($helpers->has('baz'));
$mustache->addHelper('baz', $baz);
$this->assertTrue($mustache->hasHelper('baz'));
$this->assertTrue($helpers->has('baz'));
// ... and a functional test
$tpl = $mustache->loadTemplate('{{foo}} - {{bar}} - {{#baz}}qux{{/baz}}');
$this->assertEquals('foo - BAR - __qux__', $tpl->render());
$this->assertEquals('foo - BAR - __qux__', $tpl->render(array('qux' => "won't mess things up")));
}
// ... and a functional test
$tpl = $mustache->loadTemplate('{{foo}} - {{bar}} - {{#baz}}qux{{/baz}}');
$this->assertEquals('foo - BAR - __qux__', $tpl->render());
$this->assertEquals('foo - BAR - __qux__', $tpl->render(array('qux' => "won't mess things up")));
}
public static function wrapWithUnderscores($text) {
return '__'.$text.'__';
}
public static function wrapWithUnderscores($text)
{
return '__'.$text.'__';
}
/**
* @expectedException InvalidArgumentException
*/
public function testSetHelpersThrowsExceptions() {
$mustache = new Mustache_Engine;
$mustache->setHelpers('monkeymonkeymonkey');
}
/**
* @expectedException InvalidArgumentException
*/
public function testSetHelpersThrowsExceptions()
{
$mustache = new Mustache_Engine;
$mustache->setHelpers('monkeymonkeymonkey');
}
private static function rmdir($path) {
$path = rtrim($path, '/').'/';
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
private static function rmdir($path)
{
$path = rtrim($path, '/').'/';
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
$fullpath = $path.$file;
if (is_dir($fullpath)) {
self::rmdir($fullpath);
} else {
unlink($fullpath);
}
}
$fullpath = $path.$file;
if (is_dir($fullpath)) {
self::rmdir($fullpath);
} else {
unlink($fullpath);
}
}
closedir($handle);
rmdir($path);
}
closedir($handle);
rmdir($path);
}
}
class MustacheStub extends Mustache_Engine {
public $source;
public $template;
public function loadTemplate($source) {
$this->source = $source;
public $source;
public $template;
public function loadTemplate($source)
{
$this->source = $source;
return $this->template;
}
return $this->template;
}
}
+18 -14
View File
@@ -13,24 +13,28 @@
* @group magic_methods
* @group functional
*/
class Mustache_Test_Functional_CallTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_Functional_CallTest extends PHPUnit_Framework_TestCase
{
public function testCallEatsContext() {
$m = new Mustache_Engine;
$tpl = $m->loadTemplate('{{# foo }}{{ label }}: {{ name }}{{/ foo }}');
public function testCallEatsContext()
{
$m = new Mustache_Engine;
$tpl = $m->loadTemplate('{{# foo }}{{ label }}: {{ name }}{{/ foo }}');
$foo = new Mustache_Test_Functional_ClassWithCall();
$foo->name = 'Bob';
$foo = new Mustache_Test_Functional_ClassWithCall();
$foo->name = 'Bob';
$data = array('label' => 'name', 'foo' => $foo);
$data = array('label' => 'name', 'foo' => $foo);
$this->assertEquals('name: Bob', $tpl->render($data));
}
$this->assertEquals('name: Bob', $tpl->render($data));
}
}
class Mustache_Test_Functional_ClassWithCall {
public $name;
public function __call($method, $args) {
return 'unknown value';
}
class Mustache_Test_Functional_ClassWithCall
{
public $name;
public function __call($method, $args)
{
return 'unknown value';
}
}
+110 -105
View File
@@ -13,125 +13,130 @@
* @group examples
* @group functional
*/
class Mustache_Test_Functional_ExamplesTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_Functional_ExamplesTest extends PHPUnit_Framework_TestCase
{
/**
* Test everything in the `examples` directory.
*
* @dataProvider getExamples
*
* @param string $context
* @param string $source
* @param array $partials
* @param string $expected
*/
public function testExamples($context, $source, $partials, $expected) {
$mustache = new Mustache_Engine(array(
'partials' => $partials
));
$this->assertEquals($expected, $mustache->loadTemplate($source)->render($context));
}
/**
* Test everything in the `examples` directory.
*
* @dataProvider getExamples
*
* @param string $context
* @param string $source
* @param array $partials
* @param string $expected
*/
public function testExamples($context, $source, $partials, $expected)
{
$mustache = new Mustache_Engine(array(
'partials' => $partials
));
$this->assertEquals($expected, $mustache->loadTemplate($source)->render($context));
}
/**
* Data provider for testExamples method.
*
* Loads examples from the test fixtures directory.
*
* This examples directory should contain any number of subdirectories, each of which contains
* three files: one Mustache class (.php), one Mustache template (.mustache), and one output file
* (.txt). Optionally, the directory may contain a folder full of partials.
*
* @return array
*/
public function getExamples() {
$path = realpath(dirname(__FILE__).'/../../../fixtures/examples');
$examples = array();
/**
* Data provider for testExamples method.
*
* Loads examples from the test fixtures directory.
*
* This examples directory should contain any number of subdirectories, each of which contains
* three files: one Mustache class (.php), one Mustache template (.mustache), and one output file
* (.txt). Optionally, the directory may contain a folder full of partials.
*
* @return array
*/
public function getExamples()
{
$path = realpath(dirname(__FILE__).'/../../../fixtures/examples');
$examples = array();
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
$fullpath = $path.'/'.$file;
if (is_dir($fullpath)) {
$examples[$file] = $this->loadExample($fullpath);
}
}
closedir($handle);
$fullpath = $path.'/'.$file;
if (is_dir($fullpath)) {
$examples[$file] = $this->loadExample($fullpath);
}
}
closedir($handle);
return $examples;
}
return $examples;
}
/**
* Helper method to load an example given the full path.
*
* @param string $path
*
* @return array arguments for testExamples
*/
private function loadExample($path) {
$context = null;
$source = null;
$partials = array();
$expected = null;
/**
* Helper method to load an example given the full path.
*
* @param string $path
*
* @return array arguments for testExamples
*/
private function loadExample($path)
{
$context = null;
$source = null;
$partials = array();
$expected = null;
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
$fullpath = $path.'/'.$file;
$info = pathinfo($fullpath);
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
$fullpath = $path.'/'.$file;
$info = pathinfo($fullpath);
if (is_dir($fullpath) && $info['basename'] == 'partials') {
// load partials
$partials = $this->loadPartials($fullpath);
} elseif (is_file($fullpath)) {
// load other files
switch ($info['extension']) {
case 'php':
require_once($fullpath);
$context = new $info['filename'];
break;
if (is_dir($fullpath) && $info['basename'] == 'partials') {
// load partials
$partials = $this->loadPartials($fullpath);
} elseif (is_file($fullpath)) {
// load other files
switch ($info['extension']) {
case 'php':
require_once($fullpath);
$context = new $info['filename'];
break;
case 'mustache':
$source = file_get_contents($fullpath);
break;
case 'mustache':
$source = file_get_contents($fullpath);
break;
case 'txt':
$expected = file_get_contents($fullpath);
break;
}
}
}
closedir($handle);
case 'txt':
$expected = file_get_contents($fullpath);
break;
}
}
}
closedir($handle);
return array($context, $source, $partials, $expected);
}
return array($context, $source, $partials, $expected);
}
/**
* Helper method to load partials given an example directory.
*
* @param string $path
*
* @return array $partials
*/
private function loadPartials($path) {
$partials = array();
/**
* Helper method to load partials given an example directory.
*
* @param string $path
*
* @return array $partials
*/
private function loadPartials($path)
{
$partials = array();
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
$handle = opendir($path);
while (($file = readdir($handle)) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
$fullpath = $path.'/'.$file;
$info = pathinfo($fullpath);
$fullpath = $path.'/'.$file;
$info = pathinfo($fullpath);
if ($info['extension'] === 'mustache') {
$partials[$info['filename']] = file_get_contents($fullpath);
}
}
closedir($handle);
if ($info['extension'] === 'mustache') {
$partials[$info['filename']] = file_get_contents($fullpath);
}
}
closedir($handle);
return $partials;
}
return $partials;
}
}
@@ -13,82 +13,94 @@
* @group lambdas
* @group functional
*/
class Mustache_Test_Functional_HigherOrderSectionsTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_Functional_HigherOrderSectionsTest extends PHPUnit_Framework_TestCase
{
private $mustache;
private $mustache;
public function setUp() {
$this->mustache = new Mustache_Engine;
}
public function setUp()
{
$this->mustache = new Mustache_Engine;
}
public function testRuntimeSectionCallback() {
$tpl = $this->mustache->loadTemplate('{{#doublewrap}}{{name}}{{/doublewrap}}');
public function testRuntimeSectionCallback()
{
$tpl = $this->mustache->loadTemplate('{{#doublewrap}}{{name}}{{/doublewrap}}');
$foo = new Mustache_Test_Functional_Foo;
$foo->doublewrap = array($foo, 'wrapWithBoth');
$foo = new Mustache_Test_Functional_Foo;
$foo->doublewrap = array($foo, 'wrapWithBoth');
$this->assertEquals(sprintf('<strong><em>%s</em></strong>', $foo->name), $tpl->render($foo));
}
$this->assertEquals(sprintf('<strong><em>%s</em></strong>', $foo->name), $tpl->render($foo));
}
public function testStaticSectionCallback() {
$tpl = $this->mustache->loadTemplate('{{#trimmer}} {{name}} {{/trimmer}}');
public function testStaticSectionCallback()
{
$tpl = $this->mustache->loadTemplate('{{#trimmer}} {{name}} {{/trimmer}}');
$foo = new Mustache_Test_Functional_Foo;
$foo->trimmer = array(get_class($foo), 'staticTrim');
$foo = new Mustache_Test_Functional_Foo;
$foo->trimmer = array(get_class($foo), 'staticTrim');
$this->assertEquals($foo->name, $tpl->render($foo));
}
$this->assertEquals($foo->name, $tpl->render($foo));
}
public function testViewArraySectionCallback() {
$tpl = $this->mustache->loadTemplate('{{#trim}} {{name}} {{/trim}}');
public function testViewArraySectionCallback()
{
$tpl = $this->mustache->loadTemplate('{{#trim}} {{name}} {{/trim}}');
$foo = new Mustache_Test_Functional_Foo;
$foo = new Mustache_Test_Functional_Foo;
$data = array(
'name' => 'Bob',
'trim' => array(get_class($foo), 'staticTrim'),
);
$data = array(
'name' => 'Bob',
'trim' => array(get_class($foo), 'staticTrim'),
);
$this->assertEquals($data['name'], $tpl->render($data));
}
$this->assertEquals($data['name'], $tpl->render($data));
}
public function testMonsters() {
$tpl = $this->mustache->loadTemplate('{{#title}}{{title}} {{/title}}{{name}}');
public function testMonsters()
{
$tpl = $this->mustache->loadTemplate('{{#title}}{{title}} {{/title}}{{name}}');
$frank = new Mustache_Test_Functional_Monster();
$frank->title = 'Dr.';
$frank->name = 'Frankenstein';
$this->assertEquals('Dr. Frankenstein', $tpl->render($frank));
$frank = new Mustache_Test_Functional_Monster();
$frank->title = 'Dr.';
$frank->name = 'Frankenstein';
$this->assertEquals('Dr. Frankenstein', $tpl->render($frank));
$dracula = new Mustache_Test_Functional_Monster();
$dracula->title = 'Count';
$dracula->name = 'Dracula';
$this->assertEquals('Count Dracula', $tpl->render($dracula));
}
$dracula = new Mustache_Test_Functional_Monster();
$dracula->title = 'Count';
$dracula->name = 'Dracula';
$this->assertEquals('Count Dracula', $tpl->render($dracula));
}
}
class Mustache_Test_Functional_Foo {
public $name = 'Justin';
public $lorem = 'Lorem ipsum dolor sit amet,';
class Mustache_Test_Functional_Foo
{
public $name = 'Justin';
public $lorem = 'Lorem ipsum dolor sit amet,';
public function wrapWithEm($text) {
return sprintf('<em>%s</em>', $text);
}
public function wrapWithEm($text)
{
return sprintf('<em>%s</em>', $text);
}
public function wrapWithStrong($text) {
return sprintf('<strong>%s</strong>', $text);
}
public function wrapWithStrong($text)
{
return sprintf('<strong>%s</strong>', $text);
}
public function wrapWithBoth($text) {
return self::wrapWithStrong(self::wrapWithEm($text));
}
public function wrapWithBoth($text)
{
return self::wrapWithStrong(self::wrapWithEm($text));
}
public static function staticTrim($text) {
return trim($text);
}
public static function staticTrim($text)
{
return trim($text);
}
}
class Mustache_Test_Functional_Monster {
public $title;
public $name;
class Mustache_Test_Functional_Monster
{
public $title;
public $name;
}
@@ -13,128 +13,140 @@
* @group mustache_injection
* @group functional
*/
class Mustache_Test_Functional_MustacheInjectionTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_Functional_MustacheInjectionTest extends PHPUnit_Framework_TestCase
{
private $mustache;
private $mustache;
public function setUp() {
$this->mustache = new Mustache_Engine;
}
public function setUp()
{
$this->mustache = new Mustache_Engine;
}
// interpolation
// interpolation
public function testInterpolationInjection() {
$tpl = $this->mustache->loadTemplate('{{ a }}');
public function testInterpolationInjection()
{
$tpl = $this->mustache->loadTemplate('{{ a }}');
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$this->assertEquals('{{ b }}', $tpl->render($data));
}
$this->assertEquals('{{ b }}', $tpl->render($data));
}
public function testUnescapedInterpolationInjection() {
$tpl = $this->mustache->loadTemplate('{{{ a }}}');
public function testUnescapedInterpolationInjection()
{
$tpl = $this->mustache->loadTemplate('{{{ a }}}');
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$this->assertEquals('{{ b }}', $tpl->render($data));
}
$this->assertEquals('{{ b }}', $tpl->render($data));
}
// sections
// sections
public function testSectionInjection() {
$tpl = $this->mustache->loadTemplate('{{# a }}{{ b }}{{/ a }}');
public function testSectionInjection()
{
$tpl = $this->mustache->loadTemplate('{{# a }}{{ b }}{{/ a }}');
$data = array(
'a' => true,
'b' => '{{ c }}',
'c' => 'FAIL'
);
$data = array(
'a' => true,
'b' => '{{ c }}',
'c' => 'FAIL'
);
$this->assertEquals('{{ c }}', $tpl->render($data));
}
$this->assertEquals('{{ c }}', $tpl->render($data));
}
public function testUnescapedSectionInjection() {
$tpl = $this->mustache->loadTemplate('{{# a }}{{{ b }}}{{/ a }}');
public function testUnescapedSectionInjection()
{
$tpl = $this->mustache->loadTemplate('{{# a }}{{{ b }}}{{/ a }}');
$data = array(
'a' => true,
'b' => '{{ c }}',
'c' => 'FAIL'
);
$data = array(
'a' => true,
'b' => '{{ c }}',
'c' => 'FAIL'
);
$this->assertEquals('{{ c }}', $tpl->render($data));
}
$this->assertEquals('{{ c }}', $tpl->render($data));
}
// partials
// partials
public function testPartialInjection() {
$tpl = $this->mustache->loadTemplate('{{> partial }}');
$this->mustache->setPartials(array(
'partial' => '{{ a }}',
));
public function testPartialInjection()
{
$tpl = $this->mustache->loadTemplate('{{> partial }}');
$this->mustache->setPartials(array(
'partial' => '{{ a }}',
));
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$this->assertEquals('{{ b }}', $tpl->render($data));
}
$this->assertEquals('{{ b }}', $tpl->render($data));
}
public function testPartialUnescapedInjection() {
$tpl = $this->mustache->loadTemplate('{{> partial }}');
$this->mustache->setPartials(array(
'partial' => '{{{ a }}}',
));
public function testPartialUnescapedInjection()
{
$tpl = $this->mustache->loadTemplate('{{> partial }}');
$this->mustache->setPartials(array(
'partial' => '{{{ a }}}',
));
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$data = array(
'a' => '{{ b }}',
'b' => 'FAIL'
);
$this->assertEquals('{{ b }}', $tpl->render($data));
}
$this->assertEquals('{{ b }}', $tpl->render($data));
}
// lambdas
// lambdas
public function testLambdaInterpolationInjection() {
$tpl = $this->mustache->loadTemplate('{{ a }}');
public function testLambdaInterpolationInjection()
{
$tpl = $this->mustache->loadTemplate('{{ a }}');
$data = array(
'a' => array($this, 'lambdaInterpolationCallback'),
'b' => '{{ c }}',
'c' => 'FAIL'
);
$data = array(
'a' => array($this, 'lambdaInterpolationCallback'),
'b' => '{{ c }}',
'c' => 'FAIL'
);
$this->assertEquals('{{ c }}', $tpl->render($data));
}
$this->assertEquals('{{ c }}', $tpl->render($data));
}
public static function lambdaInterpolationCallback() {
return '{{ b }}';
}
public static function lambdaInterpolationCallback()
{
return '{{ b }}';
}
public function testLambdaSectionInjection() {
$tpl = $this->mustache->loadTemplate('{{# a }}b{{/ a }}');
public function testLambdaSectionInjection()
{
$tpl = $this->mustache->loadTemplate('{{# a }}b{{/ a }}');
$data = array(
'a' => array($this, 'lambdaSectionCallback'),
'b' => '{{ c }}',
'c' => 'FAIL'
);
$data = array(
'a' => array($this, 'lambdaSectionCallback'),
'b' => '{{ c }}',
'c' => 'FAIL'
);
$this->assertEquals('{{ c }}', $tpl->render($data));
}
$this->assertEquals('{{ c }}', $tpl->render($data));
}
public static function lambdaSectionCallback($text) {
return '{{ ' . $text . ' }}';
}
public static function lambdaSectionCallback($text)
{
return '{{ ' . $text . ' }}';
}
}
+134 -117
View File
@@ -15,144 +15,161 @@
* @group mustache-spec
* @group functional
*/
class Mustache_Test_Functional_MustacheSpecTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_Functional_MustacheSpecTest extends PHPUnit_Framework_TestCase
{
private static $mustache;
private static $mustache;
public static function setUpBeforeClass() {
self::$mustache = new Mustache_Engine;
}
public static function setUpBeforeClass()
{
self::$mustache = new Mustache_Engine;
}
/**
* For some reason data providers can't mark tests skipped, so this test exists
* simply to provide a 'skipped' test if the `spec` submodule isn't initialized.
*/
public function testSpecInitialized() {
if (!file_exists(dirname(__FILE__).'/../../../../vendor/spec/specs/')) {
$this->markTestSkipped('Mustache spec submodule not initialized: run "git submodule update --init"');
}
}
/**
* For some reason data providers can't mark tests skipped, so this test exists
* simply to provide a 'skipped' test if the `spec` submodule isn't initialized.
*/
public function testSpecInitialized()
{
if (!file_exists(dirname(__FILE__).'/../../../../vendor/spec/specs/')) {
$this->markTestSkipped('Mustache spec submodule not initialized: run "git submodule update --init"');
}
}
/**
* @group comments
* @dataProvider loadCommentSpec
*/
public function testCommentSpec($desc, $source, $partials, $data, $expected) {
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
/**
* @group comments
* @dataProvider loadCommentSpec
*/
public function testCommentSpec($desc, $source, $partials, $data, $expected)
{
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
public function loadCommentSpec() {
return $this->loadSpec('comments');
}
public function loadCommentSpec()
{
return $this->loadSpec('comments');
}
/**
* @group delimiters
* @dataProvider loadDelimitersSpec
*/
public function testDelimitersSpec($desc, $source, $partials, $data, $expected) {
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
/**
* @group delimiters
* @dataProvider loadDelimitersSpec
*/
public function testDelimitersSpec($desc, $source, $partials, $data, $expected)
{
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
public function loadDelimitersSpec() {
return $this->loadSpec('delimiters');
}
public function loadDelimitersSpec()
{
return $this->loadSpec('delimiters');
}
/**
* @group interpolation
* @dataProvider loadInterpolationSpec
*/
public function testInterpolationSpec($desc, $source, $partials, $data, $expected) {
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
/**
* @group interpolation
* @dataProvider loadInterpolationSpec
*/
public function testInterpolationSpec($desc, $source, $partials, $data, $expected)
{
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
public function loadInterpolationSpec() {
return $this->loadSpec('interpolation');
}
public function loadInterpolationSpec()
{
return $this->loadSpec('interpolation');
}
/**
* @group inverted
* @group inverted-sections
* @dataProvider loadInvertedSpec
*/
public function testInvertedSpec($desc, $source, $partials, $data, $expected) {
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
/**
* @group inverted
* @group inverted-sections
* @dataProvider loadInvertedSpec
*/
public function testInvertedSpec($desc, $source, $partials, $data, $expected)
{
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
public function loadInvertedSpec() {
return $this->loadSpec('inverted');
}
public function loadInvertedSpec()
{
return $this->loadSpec('inverted');
}
/**
* @group partials
* @dataProvider loadPartialsSpec
*/
public function testPartialsSpec($desc, $source, $partials, $data, $expected) {
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
/**
* @group partials
* @dataProvider loadPartialsSpec
*/
public function testPartialsSpec($desc, $source, $partials, $data, $expected)
{
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
public function loadPartialsSpec() {
return $this->loadSpec('partials');
}
public function loadPartialsSpec()
{
return $this->loadSpec('partials');
}
/**
* @group sections
* @dataProvider loadSectionsSpec
*/
public function testSectionsSpec($desc, $source, $partials, $data, $expected) {
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
/**
* @group sections
* @dataProvider loadSectionsSpec
*/
public function testSectionsSpec($desc, $source, $partials, $data, $expected)
{
$template = self::loadTemplate($source, $partials);
$this->assertEquals($expected, $template->render($data), $desc);
}
public function loadSectionsSpec() {
return $this->loadSpec('sections');
}
public function loadSectionsSpec()
{
return $this->loadSpec('sections');
}
/**
* Data provider for the mustache spec test.
*
* Loads YAML files from the spec and converts them to PHPisms.
*
* @access public
* @return array
*/
private function loadSpec($name) {
$filename = dirname(__FILE__) . '/../../../../vendor/spec/specs/' . $name . '.yml';
if (!file_exists($filename)) {
return array();
}
/**
* Data provider for the mustache spec test.
*
* Loads YAML files from the spec and converts them to PHPisms.
*
* @access public
* @return array
*/
private function loadSpec($name)
{
$filename = dirname(__FILE__) . '/../../../../vendor/spec/specs/' . $name . '.yml';
if (!file_exists($filename)) {
return array();
}
$data = array();
$yaml = new sfYamlParser;
$file = file_get_contents($filename);
$data = array();
$yaml = new sfYamlParser;
$file = file_get_contents($filename);
// @hack: pre-process the 'lambdas' spec so the Symfony YAML parser doesn't complain.
if ($name === '~lambdas') {
$file = str_replace(" !code\n", "\n", $file);
}
// @hack: pre-process the 'lambdas' spec so the Symfony YAML parser doesn't complain.
if ($name === '~lambdas') {
$file = str_replace(" !code\n", "\n", $file);
}
$spec = $yaml->parse($file);
$spec = $yaml->parse($file);
foreach ($spec['tests'] as $test) {
$data[] = array(
$test['name'] . ': ' . $test['desc'],
$test['template'],
isset($test['partials']) ? $test['partials'] : array(),
$test['data'],
$test['expected'],
);
}
foreach ($spec['tests'] as $test) {
$data[] = array(
$test['name'] . ': ' . $test['desc'],
$test['template'],
isset($test['partials']) ? $test['partials'] : array(),
$test['data'],
$test['expected'],
);
}
return $data;
}
return $data;
}
private static function loadTemplate($source, $partials) {
self::$mustache->setPartials($partials);
private static function loadTemplate($source, $partials)
{
self::$mustache->setPartials($partials);
return self::$mustache->loadTemplate($source);
}
return self::$mustache->loadTemplate($source);
}
}
@@ -13,82 +13,98 @@
* @group sections
* @group functional
*/
class Mustache_Test_Functional_ObjectSectionTest extends PHPUnit_Framework_TestCase {
private $mustache;
class Mustache_Test_Functional_ObjectSectionTest extends PHPUnit_Framework_TestCase
{
private $mustache;
public function setUp() {
$this->mustache = new Mustache_Engine;
}
public function setUp()
{
$this->mustache = new Mustache_Engine;
}
public function testBasicObject() {
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
$this->assertEquals('Foo', $tpl->render(new Mustache_Test_Functional_Alpha));
}
public function testBasicObject()
{
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
$this->assertEquals('Foo', $tpl->render(new Mustache_Test_Functional_Alpha));
}
/**
* @group magic_methods
*/
public function testObjectWithGet() {
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
$this->assertEquals('Foo', $tpl->render(new Mustache_Test_Functional_Beta));
}
/**
* @group magic_methods
*/
public function testObjectWithGet()
{
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
$this->assertEquals('Foo', $tpl->render(new Mustache_Test_Functional_Beta));
}
/**
* @group magic_methods
*/
public function testSectionObjectWithGet() {
$tpl = $this->mustache->loadTemplate('{{#bar}}{{#foo}}{{name}}{{/foo}}{{/bar}}');
$this->assertEquals('Foo', $tpl->render(new Mustache_Test_Functional_Gamma));
}
/**
* @group magic_methods
*/
public function testSectionObjectWithGet()
{
$tpl = $this->mustache->loadTemplate('{{#bar}}{{#foo}}{{name}}{{/foo}}{{/bar}}');
$this->assertEquals('Foo', $tpl->render(new Mustache_Test_Functional_Gamma));
}
public function testSectionObjectWithFunction() {
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
$alpha = new Mustache_Test_Functional_Alpha;
$alpha->foo = new Mustache_Test_Functional_Delta;
$this->assertEquals('Foo', $tpl->render($alpha));
}
public function testSectionObjectWithFunction()
{
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
$alpha = new Mustache_Test_Functional_Alpha;
$alpha->foo = new Mustache_Test_Functional_Delta;
$this->assertEquals('Foo', $tpl->render($alpha));
}
}
class Mustache_Test_Functional_Alpha {
public $foo;
class Mustache_Test_Functional_Alpha
{
public $foo;
public function __construct() {
$this->foo = new StdClass();
$this->foo->name = 'Foo';
$this->foo->number = 1;
}
public function __construct()
{
$this->foo = new StdClass();
$this->foo->name = 'Foo';
$this->foo->number = 1;
}
}
class Mustache_Test_Functional_Beta {
protected $_data = array();
class Mustache_Test_Functional_Beta
{
protected $_data = array();
public function __construct() {
$this->_data['foo'] = new StdClass();
$this->_data['foo']->name = 'Foo';
$this->_data['foo']->number = 1;
}
public function __construct()
{
$this->_data['foo'] = new StdClass();
$this->_data['foo']->name = 'Foo';
$this->_data['foo']->number = 1;
}
public function __isset($name) {
return array_key_exists($name, $this->_data);
}
public function __isset($name)
{
return array_key_exists($name, $this->_data);
}
public function __get($name) {
return $this->_data[$name];
}
public function __get($name)
{
return $this->_data[$name];
}
}
class Mustache_Test_Functional_Gamma {
public $bar;
class Mustache_Test_Functional_Gamma
{
public $bar;
public function __construct() {
$this->bar = new Mustache_Test_Functional_Beta;
}
public function __construct()
{
$this->bar = new Mustache_Test_Functional_Beta;
}
}
class Mustache_Test_Functional_Delta {
protected $_name = 'Foo';
class Mustache_Test_Functional_Delta
{
protected $_name = 'Foo';
public function name() {
return $this->_name;
}
public function name()
{
return $this->_name;
}
}
+25 -18
View File
@@ -9,27 +9,31 @@
* file that was distributed with this source code.
*/
class Mustache_Test_HelperCollectionTest extends PHPUnit_Framework_TestCase {
public function testConstructor() {
$foo = array($this, 'getFoo');
$bar = 'BAR';
class Mustache_Test_HelperCollectionTest extends PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$foo = array($this, 'getFoo');
$bar = 'BAR';
$helpers = new Mustache_HelperCollection(array(
'foo' => $foo,
'bar' => $bar,
));
$helpers = new Mustache_HelperCollection(array(
'foo' => $foo,
'bar' => $bar,
));
$this->assertSame($foo, $helpers->get('foo'));
$this->assertSame($bar, $helpers->get('bar'));
}
$this->assertSame($foo, $helpers->get('foo'));
$this->assertSame($bar, $helpers->get('bar'));
}
public static function getFoo() {
public static function getFoo()
{
echo 'foo';
}
public function testAccessorsAndMutators() {
$foo = array($this, 'getFoo');
$bar = 'BAR';
public function testAccessorsAndMutators()
{
$foo = array($this, 'getFoo');
$bar = 'BAR';
$helpers = new Mustache_HelperCollection;
$this->assertTrue($helpers->isEmpty());
@@ -52,7 +56,8 @@ class Mustache_Test_HelperCollectionTest extends PHPUnit_Framework_TestCase {
$this->assertTrue($helpers->has('bar'));
}
public function testMagicMethods() {
public function testMagicMethods()
{
$foo = array($this, 'getFoo');
$bar = 'BAR';
@@ -88,7 +93,8 @@ class Mustache_Test_HelperCollectionTest extends PHPUnit_Framework_TestCase {
/**
* @dataProvider getInvalidHelperArguments
*/
public function testHelperCollectionIsntAfraidToThrowExceptions($helpers = array(), $actions = array(), $exception = null) {
public function testHelperCollectionIsntAfraidToThrowExceptions($helpers = array(), $actions = array(), $exception = null)
{
if ($exception) {
$this->setExpectedException($exception);
}
@@ -100,7 +106,8 @@ class Mustache_Test_HelperCollectionTest extends PHPUnit_Framework_TestCase {
}
}
public function getInvalidHelperArguments() {
public function getInvalidHelperArguments()
{
return array(
array(
'not helpers',
+32 -28
View File
@@ -12,37 +12,41 @@
/**
* @group unit
*/
class Mustache_Test_Loader_ArrayLoaderTest extends PHPUnit_Framework_TestCase {
public function testConstructor() {
$loader = new Mustache_Loader_ArrayLoader(array(
'foo' => 'bar'
));
class Mustache_Test_Loader_ArrayLoaderTest extends PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$loader = new Mustache_Loader_ArrayLoader(array(
'foo' => 'bar'
));
$this->assertEquals('bar', $loader->load('foo'));
}
$this->assertEquals('bar', $loader->load('foo'));
}
public function testSetAndLoadTemplates() {
$loader = new Mustache_Loader_ArrayLoader(array(
'foo' => 'bar'
));
$this->assertEquals('bar', $loader->load('foo'));
public function testSetAndLoadTemplates()
{
$loader = new Mustache_Loader_ArrayLoader(array(
'foo' => 'bar'
));
$this->assertEquals('bar', $loader->load('foo'));
$loader->setTemplate('baz', 'qux');
$this->assertEquals('qux', $loader->load('baz'));
$loader->setTemplate('baz', 'qux');
$this->assertEquals('qux', $loader->load('baz'));
$loader->setTemplates(array(
'foo' => 'FOO',
'baz' => 'BAZ',
));
$this->assertEquals('FOO', $loader->load('foo'));
$this->assertEquals('BAZ', $loader->load('baz'));
}
$loader->setTemplates(array(
'foo' => 'FOO',
'baz' => 'BAZ',
));
$this->assertEquals('FOO', $loader->load('foo'));
$this->assertEquals('BAZ', $loader->load('baz'));
}
/**
* @expectedException InvalidArgumentException
*/
public function testMissingTemplatesThrowExceptions() {
$loader = new Mustache_Loader_ArrayLoader;
$loader->load('not_a_real_template');
}
/**
* @expectedException InvalidArgumentException
*/
public function testMissingTemplatesThrowExceptions()
{
$loader = new Mustache_Loader_ArrayLoader;
$loader->load('not_a_real_template');
}
}
@@ -12,35 +12,40 @@
/**
* @group unit
*/
class Mustache_Test_Loader_FilesystemLoaderTest extends PHPUnit_Framework_TestCase {
public function testConstructor() {
$baseDir = realpath(dirname(__FILE__).'/../../../fixtures/templates');
$loader = new Mustache_Loader_FilesystemLoader($baseDir, array('extension' => '.ms'));
$this->assertEquals('alpha contents', $loader->load('alpha'));
$this->assertEquals('beta contents', $loader->load('beta.ms'));
}
class Mustache_Test_Loader_FilesystemLoaderTest extends PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$baseDir = realpath(dirname(__FILE__).'/../../../fixtures/templates');
$loader = new Mustache_Loader_FilesystemLoader($baseDir, array('extension' => '.ms'));
$this->assertEquals('alpha contents', $loader->load('alpha'));
$this->assertEquals('beta contents', $loader->load('beta.ms'));
}
public function testLoadTemplates() {
$baseDir = realpath(dirname(__FILE__).'/../../../fixtures/templates');
$loader = new Mustache_Loader_FilesystemLoader($baseDir);
$this->assertEquals('one contents', $loader->load('one'));
$this->assertEquals('two contents', $loader->load('two.mustache'));
}
public function testLoadTemplates()
{
$baseDir = realpath(dirname(__FILE__).'/../../../fixtures/templates');
$loader = new Mustache_Loader_FilesystemLoader($baseDir);
$this->assertEquals('one contents', $loader->load('one'));
$this->assertEquals('two contents', $loader->load('two.mustache'));
}
/**
* @expectedException RuntimeException
*/
public function testMissingBaseDirThrowsException() {
$loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/not_a_directory');
}
/**
* @expectedException RuntimeException
*/
public function testMissingBaseDirThrowsException()
{
$loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/not_a_directory');
}
/**
* @expectedException InvalidArgumentException
*/
public function testMissingTemplateThrowsException() {
$baseDir = realpath(dirname(__FILE__).'/../../../fixtures/templates');
$loader = new Mustache_Loader_FilesystemLoader($baseDir);
/**
* @expectedException InvalidArgumentException
*/
public function testMissingTemplateThrowsException()
{
$baseDir = realpath(dirname(__FILE__).'/../../../fixtures/templates');
$loader = new Mustache_Loader_FilesystemLoader($baseDir);
$loader->load('fake');
}
$loader->load('fake');
}
}
@@ -12,12 +12,14 @@
/**
* @group unit
*/
class Mustache_Test_Loader_StringLoaderTest extends PHPUnit_Framework_TestCase {
public function testLoadTemplates() {
$loader = new Mustache_Loader_StringLoader;
class Mustache_Test_Loader_StringLoaderTest extends PHPUnit_Framework_TestCase
{
public function testLoadTemplates()
{
$loader = new Mustache_Loader_StringLoader;
$this->assertEquals('foo', $loader->load('foo'));
$this->assertEquals('{{ bar }}', $loader->load('{{ bar }}'));
$this->assertEquals("\n{{! comment }}\n", $loader->load("\n{{! comment }}\n"));
}
$this->assertEquals('foo', $loader->load('foo'));
$this->assertEquals('{{ bar }}', $loader->load('{{ bar }}'));
$this->assertEquals("\n{{! comment }}\n", $loader->load("\n{{! comment }}\n"));
}
}
+156 -153
View File
@@ -12,168 +12,171 @@
/**
* @group unit
*/
class Mustache_Test_ParserTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_ParserTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider getTokenSets
*/
public function testParse($tokens, $expected)
{
$parser = new Mustache_Parser;
$this->assertEquals($expected, $parser->parse($tokens));
}
/**
* @dataProvider getTokenSets
*/
public function testParse($tokens, $expected)
{
$parser = new Mustache_Parser;
$this->assertEquals($expected, $parser->parse($tokens));
}
public function getTokenSets()
{
return array(
array(
array(),
array()
),
public function getTokenSets()
{
return array(
array(
array(),
array()
),
array(
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text'
)),
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text'
)),
),
array(
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text'
)),
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text'
)),
),
array(
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
)),
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
)),
),
array(
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
)),
array(array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
)),
),
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'foo'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_INVERTED,
Mustache_Tokenizer::INDEX => 123,
Mustache_Tokenizer::NAME => 'parent'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::INDEX => 456,
Mustache_Tokenizer::NAME => 'parent'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'bar'
),
),
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'foo'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_INVERTED,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
Mustache_Tokenizer::END => 456,
Mustache_Tokenizer::NODES => array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
),
),
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'bar'
),
),
),
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'foo'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_INVERTED,
Mustache_Tokenizer::INDEX => 123,
Mustache_Tokenizer::NAME => 'parent'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::INDEX => 456,
Mustache_Tokenizer::NAME => 'parent'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'bar'
),
),
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'foo'
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_INVERTED,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
Mustache_Tokenizer::END => 456,
Mustache_Tokenizer::NODES => array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name'
),
),
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'bar'
),
),
),
);
}
);
}
/**
* @dataProvider getBadParseTrees
* @expectedException LogicException
*/
public function testParserThrowsExceptions($tokens) {
$parser = new Mustache_Parser;
$parser->parse($tokens);
}
/**
* @dataProvider getBadParseTrees
* @expectedException LogicException
*/
public function testParserThrowsExceptions($tokens)
{
$parser = new Mustache_Parser;
$parser->parse($tokens);
}
public function getBadParseTrees() {
return array(
// no close
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
),
),
public function getBadParseTrees()
{
return array(
// no close
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
),
),
// no close inverted
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_INVERTED,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
),
),
// no close inverted
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_INVERTED,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
),
),
// no opening inverted
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
),
),
// no opening inverted
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
),
),
// weird nesting
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'child',
Mustache_Tokenizer::INDEX => 123,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'child',
Mustache_Tokenizer::INDEX => 123,
),
),
),
);
}
// weird nesting
array(
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'child',
Mustache_Tokenizer::INDEX => 123,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'parent',
Mustache_Tokenizer::INDEX => 123,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'child',
Mustache_Tokenizer::INDEX => 123,
),
),
),
);
}
}
+33 -27
View File
@@ -12,38 +12,44 @@
/**
* @group unit
*/
class Mustache_Test_TemplateTest extends PHPUnit_Framework_TestCase {
public function testConstructor() {
$mustache = new Mustache_Engine;
$template = new Mustache_Test_TemplateStub($mustache);
$this->assertSame($mustache, $template->getMustache());
}
class Mustache_Test_TemplateTest extends PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$mustache = new Mustache_Engine;
$template = new Mustache_Test_TemplateStub($mustache);
$this->assertSame($mustache, $template->getMustache());
}
public function testRendering() {
$rendered = '<< wheee >>';
$mustache = new Mustache_Engine;
$template = new Mustache_Test_TemplateStub($mustache);
$template->rendered = $rendered;
$context = new Mustache_Context;
public function testRendering()
{
$rendered = '<< wheee >>';
$mustache = new Mustache_Engine;
$template = new Mustache_Test_TemplateStub($mustache);
$template->rendered = $rendered;
$context = new Mustache_Context;
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$this->assertEquals($rendered, $template());
}
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$this->assertEquals($rendered, $template());
}
$this->assertEquals($rendered, $template->render());
$this->assertEquals($rendered, $template->renderInternal($context));
$this->assertEquals($rendered, $template->render(array('foo' => 'bar')));
}
$this->assertEquals($rendered, $template->render());
$this->assertEquals($rendered, $template->renderInternal($context));
$this->assertEquals($rendered, $template->render(array('foo' => 'bar')));
}
}
class Mustache_Test_TemplateStub extends Mustache_Template {
public $rendered;
class Mustache_Test_TemplateStub extends Mustache_Template
{
public $rendered;
public function getMustache() {
return $this->mustache;
}
public function getMustache()
{
return $this->mustache;
}
public function renderInternal(Mustache_Context $context, $indent = '', $escape = false) {
return $this->rendered;
}
public function renderInternal(Mustache_Context $context, $indent = '', $escape = false)
{
return $this->rendered;
}
}
+121 -118
View File
@@ -12,130 +12,133 @@
/**
* @group unit
*/
class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase {
class Mustache_Test_TokenizerTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider getTokens
*/
public function testScan($text, $delimiters, $expected) {
$tokenizer = new Mustache_Tokenizer;
$this->assertSame($expected, $tokenizer->scan($text, $delimiters));
}
/**
* @dataProvider getTokens
*/
public function testScan($text, $delimiters, $expected)
{
$tokenizer = new Mustache_Tokenizer;
$this->assertSame($expected, $tokenizer->scan($text, $delimiters));
}
public function getTokens() {
return array(
array(
'text',
null,
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text',
),
),
),
public function getTokens()
{
return array(
array(
'text',
null,
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text',
),
),
),
array(
'text',
'<<< >>>',
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text',
),
),
),
array(
'text',
'<<< >>>',
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => 'text',
),
),
),
array(
'{{ name }}',
null,
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name',
Mustache_Tokenizer::OTAG => '{{',
Mustache_Tokenizer::CTAG => '}}',
Mustache_Tokenizer::INDEX => 10,
)
)
),
array(
'{{ name }}',
null,
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name',
Mustache_Tokenizer::OTAG => '{{',
Mustache_Tokenizer::CTAG => '}}',
Mustache_Tokenizer::INDEX => 10,
)
)
),
array(
'{{ name }}',
'<<< >>>',
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => '{{ name }}',
),
),
),
array(
'{{ name }}',
'<<< >>>',
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => '{{ name }}',
),
),
),
array(
'<<< name >>>',
'<<< >>>',
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name',
Mustache_Tokenizer::OTAG => '<<<',
Mustache_Tokenizer::CTAG => '>>>',
Mustache_Tokenizer::INDEX => 12,
)
)
),
array(
'<<< name >>>',
'<<< >>>',
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'name',
Mustache_Tokenizer::OTAG => '<<<',
Mustache_Tokenizer::CTAG => '>>>',
Mustache_Tokenizer::INDEX => 12,
)
)
),
array(
"{{{ a }}}\n{{# b }} \n{{= | | =}}| c ||/ b |\n|{ d }|",
null,
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_UNESCAPED,
Mustache_Tokenizer::NAME => 'a',
Mustache_Tokenizer::OTAG => '{{',
Mustache_Tokenizer::CTAG => '}}',
Mustache_Tokenizer::INDEX => 8,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => "\n",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'b',
Mustache_Tokenizer::OTAG => '{{',
Mustache_Tokenizer::CTAG => '}}',
Mustache_Tokenizer::INDEX => 18,
),
null,
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'c',
Mustache_Tokenizer::OTAG => '|',
Mustache_Tokenizer::CTAG => '|',
Mustache_Tokenizer::INDEX => 37,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'b',
Mustache_Tokenizer::OTAG => '|',
Mustache_Tokenizer::CTAG => '|',
Mustache_Tokenizer::INDEX => 37,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => "\n",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_UNESCAPED,
Mustache_Tokenizer::NAME => 'd',
Mustache_Tokenizer::OTAG => '|',
Mustache_Tokenizer::CTAG => '|',
Mustache_Tokenizer::INDEX => 51,
),
array(
"{{{ a }}}\n{{# b }} \n{{= | | =}}| c ||/ b |\n|{ d }|",
null,
array(
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_UNESCAPED,
Mustache_Tokenizer::NAME => 'a',
Mustache_Tokenizer::OTAG => '{{',
Mustache_Tokenizer::CTAG => '}}',
Mustache_Tokenizer::INDEX => 8,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => "\n",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_SECTION,
Mustache_Tokenizer::NAME => 'b',
Mustache_Tokenizer::OTAG => '{{',
Mustache_Tokenizer::CTAG => '}}',
Mustache_Tokenizer::INDEX => 18,
),
null,
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_ESCAPED,
Mustache_Tokenizer::NAME => 'c',
Mustache_Tokenizer::OTAG => '|',
Mustache_Tokenizer::CTAG => '|',
Mustache_Tokenizer::INDEX => 37,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_END_SECTION,
Mustache_Tokenizer::NAME => 'b',
Mustache_Tokenizer::OTAG => '|',
Mustache_Tokenizer::CTAG => '|',
Mustache_Tokenizer::INDEX => 37,
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_TEXT,
Mustache_Tokenizer::VALUE => "\n",
),
array(
Mustache_Tokenizer::TYPE => Mustache_Tokenizer::T_UNESCAPED,
Mustache_Tokenizer::NAME => 'd',
Mustache_Tokenizer::OTAG => '|',
Mustache_Tokenizer::CTAG => '|',
Mustache_Tokenizer::INDEX => 51,
),
)
),
);
}
)
),
);
}
}
+3 -2
View File
@@ -9,6 +9,7 @@
* file that was distributed with this source code.
*/
class Mustache_Bar {
// nada
class Mustache_Bar
{
// nada
}
+3 -2
View File
@@ -9,6 +9,7 @@
* file that was distributed with this source code.
*/
class Mustache_Foo {
// nada
class Mustache_Foo
{
// nada
}
+3 -2
View File
@@ -9,6 +9,7 @@
* file that was distributed with this source code.
*/
class NonMustacheClass {
// noop
class NonMustacheClass
{
// noop
}
+10 -9
View File
@@ -1,13 +1,14 @@
<?php
class ChildContext {
public $parent = array(
'child' => 'child works',
);
class ChildContext
{
public $parent = array(
'child' => 'child works',
);
public $grandparent = array(
'parent' => array(
'child' => 'grandchild works',
),
);
public $grandparent = array(
'parent' => array(
'child' => 'grandchild works',
),
);
}
+6 -4
View File
@@ -1,7 +1,9 @@
<?php
class Comments {
public function title() {
return 'A Comedy of Errors';
}
class Comments
{
public function title()
{
return 'A Comedy of Errors';
}
}
+16 -13
View File
@@ -1,19 +1,22 @@
<?php
class Complex {
public $header = 'Colors';
class Complex
{
public $header = 'Colors';
public $item = array(
array('name' => 'red', 'current' => true, 'url' => '#Red'),
array('name' => 'green', 'current' => false, 'url' => '#Green'),
array('name' => 'blue', 'current' => false, 'url' => '#Blue'),
);
public $item = array(
array('name' => 'red', 'current' => true, 'url' => '#Red'),
array('name' => 'green', 'current' => false, 'url' => '#Green'),
array('name' => 'blue', 'current' => false, 'url' => '#Blue'),
);
public function notEmpty() {
return !($this->isEmpty());
}
public function notEmpty()
{
return !($this->isEmpty());
}
public function isEmpty() {
return count($this->item) === 0;
}
public function isEmpty()
{
return count($this->item) === 0;
}
}
+11 -9
View File
@@ -1,14 +1,16 @@
<?php
class Delimiters {
public $start = "It worked the first time.";
class Delimiters
{
public $start = "It worked the first time.";
public function middle() {
return array(
array('item' => "And it worked the second time."),
array('item' => "As well as the third."),
);
}
public function middle()
{
return array(
array('item' => "And it worked the second time."),
array('item' => "As well as the third."),
);
}
public $final = "Then, surprisingly, it worked the final time.";
public $final = "Then, surprisingly, it worked the final time.";
}
+11 -10
View File
@@ -1,14 +1,15 @@
<?php
class DotNotation {
public $person = array(
'name' => array('first' => 'Chris', 'last' => 'Firescythe'),
'age' => 24,
'hometown' => array(
'city' => 'Cincinnati',
'state' => 'OH',
)
);
class DotNotation
{
public $person = array(
'name' => array('first' => 'Chris', 'last' => 'Firescythe'),
'age' => 24,
'hometown' => array(
'city' => 'Cincinnati',
'state' => 'OH',
)
);
public $normal = 'Normal';
public $normal = 'Normal';
}
+7 -5
View File
@@ -1,9 +1,11 @@
<?php
class DoubleSection {
public function t() {
return true;
}
class DoubleSection
{
public function t()
{
return true;
}
public $two = "second";
public $two = "second";
}
+3 -2
View File
@@ -1,5 +1,6 @@
<?php
class Escaped {
public $title = '"Bear" > "Shark"';
class Escaped
{
public $title = '"Bear" > "Shark"';
}
@@ -1,22 +1,24 @@
<?php
class GrandParentContext {
public $grand_parent_id = 'grand_parent1';
public $parent_contexts = array();
class GrandParentContext
{
public $grand_parent_id = 'grand_parent1';
public $parent_contexts = array();
public function __construct() {
$this->parent_contexts[] = array('parent_id' => 'parent1', 'child_contexts' => array(
array('child_id' => 'parent1-child1'),
array('child_id' => 'parent1-child2')
));
public function __construct()
{
$this->parent_contexts[] = array('parent_id' => 'parent1', 'child_contexts' => array(
array('child_id' => 'parent1-child1'),
array('child_id' => 'parent1-child2')
));
$parent2 = new stdClass();
$parent2->parent_id = 'parent2';
$parent2->child_contexts = array(
array('child_id' => 'parent2-child1'),
array('child_id' => 'parent2-child2')
);
$parent2 = new stdClass();
$parent2->parent_id = 'parent2';
$parent2->child_contexts = array(
array('child_id' => 'parent2-child1'),
array('child_id' => 'parent2-child2')
);
$this->parent_contexts[] = $parent2;
}
$this->parent_contexts[] = $parent2;
}
}
+4 -2
View File
@@ -1,6 +1,7 @@
<?php
class I18n {
class I18n
{
// Variable to be interpolated
public $name = 'Bob';
@@ -14,7 +15,8 @@ class I18n {
'My name is {{ name }}.' => 'Me llamo {{ name }}.',
);
public static function __trans($text) {
public static function __trans($text)
{
return isset(self::$dictionary[$text]) ? self::$dictionary[$text] : $text;
}
}
@@ -1,5 +1,6 @@
<?php
class ImplicitIterator {
public $data = array('Donkey Kong', 'Luigi', 'Mario', 'Peach', 'Yoshi');
class ImplicitIterator
{
public $data = array('Donkey Kong', 'Luigi', 'Mario', 'Peach', 'Yoshi');
}
@@ -1,6 +1,7 @@
<?php
class InvertedDoubleSection {
public $t = false;
public $two = 'second';
class InvertedDoubleSection
{
public $t = false;
public $two = 'second';
}
@@ -1,5 +1,6 @@
<?php
class InvertedSection {
public $repo = array();
class InvertedSection
{
public $repo = array();
}
@@ -1,12 +1,13 @@
<?php
class RecursivePartials {
public $name = 'George';
public $child = array(
'name' => 'Dan',
'child' => array(
'name' => 'Justin',
'child' => false,
)
);
class RecursivePartials
{
public $name = 'George';
public $child = array(
'name' => 'Dan',
'child' => array(
'name' => 'Justin',
'child' => false,
)
);
}
@@ -1,16 +1,18 @@
<?php
class SectionIteratorObjects {
public $start = "It worked the first time.";
class SectionIteratorObjects
{
public $start = "It worked the first time.";
protected $_data = array(
array('item' => 'And it worked the second time.'),
array('item' => 'As well as the third.'),
);
protected $_data = array(
array('item' => 'And it worked the second time.'),
array('item' => 'As well as the third.'),
);
public function middle() {
return new ArrayIterator($this->_data);
}
public function middle()
{
return new ArrayIterator($this->_data);
}
public $final = "Then, surprisingly, it worked the final time.";
public $final = "Then, surprisingly, it worked the final time.";
}
@@ -1,26 +1,31 @@
<?php
class SectionMagicObjects {
public $start = "It worked the first time.";
class SectionMagicObjects
{
public $start = "It worked the first time.";
public function middle() {
return new MagicObject();
}
public function middle()
{
return new MagicObject();
}
public $final = "Then, surprisingly, it worked the final time.";
public $final = "Then, surprisingly, it worked the final time.";
}
class MagicObject {
protected $_data = array(
'foo' => 'And it worked the second time.',
'bar' => 'As well as the third.'
);
class MagicObject
{
protected $_data = array(
'foo' => 'And it worked the second time.',
'bar' => 'As well as the third.'
);
public function __get($key) {
return isset($this->_data[$key]) ? $this->_data[$key] : NULL;
}
public function __get($key)
{
return isset($this->_data[$key]) ? $this->_data[$key] : NULL;
}
public function __isset($key) {
return isset($this->_data[$key]);
}
public function __isset($key)
{
return isset($this->_data[$key]);
}
}
+12 -9
View File
@@ -1,16 +1,19 @@
<?php
class SectionObjects {
public $start = "It worked the first time.";
class SectionObjects
{
public $start = "It worked the first time.";
public function middle() {
return new SectionObject;
}
public function middle()
{
return new SectionObject;
}
public $final = "Then, surprisingly, it worked the final time.";
public $final = "Then, surprisingly, it worked the final time.";
}
class SectionObject {
public $foo = 'And it worked the second time.';
public $bar = 'As well as the third.';
class SectionObject
{
public $foo = 'And it worked the second time.';
public $bar = 'As well as the third.';
}
+11 -9
View File
@@ -1,14 +1,16 @@
<?php
class Sections {
public $start = "It worked the first time.";
class Sections
{
public $start = "It worked the first time.";
public function middle() {
return array(
array('item' => "And it worked the second time."),
array('item' => "As well as the third."),
);
}
public function middle()
{
return array(
array('item' => "And it worked the second time."),
array('item' => "As well as the third."),
);
}
public $final = "Then, surprisingly, it worked the final time.";
public $final = "Then, surprisingly, it worked the final time.";
}
+31 -29
View File
@@ -1,33 +1,35 @@
<?php
class SectionsNested {
public $name = 'Little Mac';
class SectionsNested
{
public $name = 'Little Mac';
public function enemies() {
return array(
array(
'name' => 'Von Kaiser',
'enemies' => array(
array('name' => 'Super Macho Man'),
array('name' => 'Piston Honda'),
array('name' => 'Mr. Sandman'),
)
),
array(
'name' => 'Mike Tyson',
'enemies' => array(
array('name' => 'Soda Popinski'),
array('name' => 'King Hippo'),
array('name' => 'Great Tiger'),
array('name' => 'Glass Joe'),
)
),
array(
'name' => 'Don Flamenco',
'enemies' => array(
array('name' => 'Bald Bull'),
)
),
);
}
public function enemies()
{
return array(
array(
'name' => 'Von Kaiser',
'enemies' => array(
array('name' => 'Super Macho Man'),
array('name' => 'Piston Honda'),
array('name' => 'Mr. Sandman'),
)
),
array(
'name' => 'Mike Tyson',
'enemies' => array(
array('name' => 'Soda Popinski'),
array('name' => 'King Hippo'),
array('name' => 'Great Tiger'),
array('name' => 'Glass Joe'),
)
),
array(
'name' => 'Don Flamenco',
'enemies' => array(
array('name' => 'Bald Bull'),
)
),
);
}
}
+9 -7
View File
@@ -1,12 +1,14 @@
<?php
class Simple {
public $name = "Chris";
public $value = 10000;
class Simple
{
public $name = "Chris";
public $value = 10000;
public function taxed_value() {
return $this->value - ($this->value * 0.4);
}
public function taxed_value()
{
return $this->value - ($this->value * 0.4);
}
public $in_ca = true;
public $in_ca = true;
};
+3 -2
View File
@@ -1,5 +1,6 @@
<?php
class Unescaped {
public $title = "Bear > Shark";
class Unescaped
{
public $title = "Bear > Shark";
}
+3 -2
View File
@@ -1,5 +1,6 @@
<?php
class UTF8 {
public $test = '中文又来啦';
class UTF8
{
public $test = '中文又来啦';
}
+3 -2
View File
@@ -1,5 +1,6 @@
<?php
class UTF8Unescaped {
public $test = '中文又来啦';
class UTF8Unescaped
{
public $test = '中文又来啦';
}
+20 -17
View File
@@ -8,24 +8,27 @@
*
* `{{> tag }}` and `{{> tag}}` and `{{>tag}}` should all be equivalent.
*/
class Whitespace {
public $foo = 'alpha';
class Whitespace
{
public $foo = 'alpha';
public $bar = 'beta';
public $bar = 'beta';
public function baz() {
return 'gamma';
}
public function baz()
{
return 'gamma';
}
public function qux() {
return array(
array('key with space' => 'A'),
array('key with space' => 'B'),
array('key with space' => 'C'),
array('key with space' => 'D'),
array('key with space' => 'E'),
array('key with space' => 'F'),
array('key with space' => 'G'),
);
}
public function qux()
{
return array(
array('key with space' => 'A'),
array('key with space' => 'B'),
array('key with space' => 'C'),
array('key with space' => 'D'),
array('key with space' => 'E'),
array('key with space' => 'F'),
array('key with space' => 'G'),
);
}
}