Merge branch 'release/2.1.0'
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
[submodule "vendor/spec"]
|
[submodule "vendor/spec"]
|
||||||
path = vendor/spec
|
path = vendor/spec
|
||||||
url = git://github.com/mustache/spec.git
|
url = https://github.com/mustache/spec.git
|
||||||
[submodule "vendor/yaml"]
|
[submodule "vendor/yaml"]
|
||||||
path = vendor/yaml
|
path = vendor/yaml
|
||||||
url = git://github.com/fabpot/yaml.git
|
url = https://github.com/fabpot/yaml.git
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Contributions welcome!
|
||||||
|
|
||||||
|
|
||||||
|
### Here's a quick guide:
|
||||||
|
|
||||||
|
1. [Fork the repo on GitHub](https://github.com/bobthecow/mustache.php).
|
||||||
|
|
||||||
|
2. Run the test suite. We only take pull requests with passing tests, and it's great to know that you have a clean slate. Make sure you have PHPUnit 3.5+, then run `phpunit` from the project directory.
|
||||||
|
|
||||||
|
3. Add tests for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, add a test!
|
||||||
|
|
||||||
|
4. Make the tests pass.
|
||||||
|
|
||||||
|
5. Push your fork to GitHub and submit a pull request against the `dev` branch.
|
||||||
|
|
||||||
|
|
||||||
|
### You can do some things to increase the chance that your pull request is accepted the first time:
|
||||||
|
|
||||||
|
* Submit one pull request per fix or feature.
|
||||||
|
* To help with that, do all your work in a feature branch (e.g. `feature/my-alsome-feature`).
|
||||||
|
* Follow the conventions you see used in the project.
|
||||||
|
* Use `phpcs --standard=PSR2` to check your changes against the coding standard.
|
||||||
|
* Write tests that fail without your code, and pass with it.
|
||||||
|
* Don't bump version numbers. Those will be updated — per [semver](http://semver.org) — once your change is merged into `master`.
|
||||||
|
* Update any documentation: docblocks, README, examples, etc.
|
||||||
|
* ... Don't update the wiki until your change is merged and released, but make a note in your pull request so we don't forget.
|
||||||
|
|
||||||
|
|
||||||
|
### Mustache.php follows the PSR-* coding standards:
|
||||||
|
|
||||||
|
* [PSR-0: Class and file naming conventions](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md)
|
||||||
|
* [PSR-1: Basic coding standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
|
||||||
|
* [PSR-2: Coding style guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
|
||||||
@@ -22,6 +22,7 @@ class Mustache_Compiler
|
|||||||
private $indentNextLine;
|
private $indentNextLine;
|
||||||
private $customEscape;
|
private $customEscape;
|
||||||
private $charset;
|
private $charset;
|
||||||
|
private $pragmas;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile a Mustache token parse tree into PHP source code.
|
* Compile a Mustache token parse tree into PHP source code.
|
||||||
@@ -36,6 +37,7 @@ class Mustache_Compiler
|
|||||||
*/
|
*/
|
||||||
public function compile($source, array $tree, $name, $customEscape = false, $charset = 'UTF-8')
|
public function compile($source, array $tree, $name, $customEscape = false, $charset = 'UTF-8')
|
||||||
{
|
{
|
||||||
|
$this->pragmas = array();
|
||||||
$this->sections = array();
|
$this->sections = array();
|
||||||
$this->source = $source;
|
$this->source = $source;
|
||||||
$this->indentNextLine = true;
|
$this->indentNextLine = true;
|
||||||
@@ -61,6 +63,10 @@ class Mustache_Compiler
|
|||||||
$level++;
|
$level++;
|
||||||
foreach ($tree as $node) {
|
foreach ($tree as $node) {
|
||||||
switch ($node[Mustache_Tokenizer::TYPE]) {
|
switch ($node[Mustache_Tokenizer::TYPE]) {
|
||||||
|
case Mustache_Tokenizer::T_PRAGMA:
|
||||||
|
$this->pragmas[$node[Mustache_Tokenizer::NAME]] = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case Mustache_Tokenizer::T_SECTION:
|
case Mustache_Tokenizer::T_SECTION:
|
||||||
$code .= $this->section(
|
$code .= $this->section(
|
||||||
$node[Mustache_Tokenizer::NODES],
|
$node[Mustache_Tokenizer::NODES],
|
||||||
@@ -118,8 +124,11 @@ class Mustache_Compiler
|
|||||||
|
|
||||||
class %s extends Mustache_Template
|
class %s extends Mustache_Template
|
||||||
{
|
{
|
||||||
|
private $lambdaHelper;
|
||||||
|
|
||||||
public function renderInternal(Mustache_Context $context, $indent = \'\', $escape = false)
|
public function renderInternal(Mustache_Context $context, $indent = \'\', $escape = false)
|
||||||
{
|
{
|
||||||
|
$this->lambdaHelper = new Mustache_LambdaHelper($this->mustache, $context);
|
||||||
$buffer = \'\';
|
$buffer = \'\';
|
||||||
%s
|
%s
|
||||||
|
|
||||||
@@ -159,7 +168,7 @@ class Mustache_Compiler
|
|||||||
if (!is_string($value) && is_callable($value)) {
|
if (!is_string($value) && is_callable($value)) {
|
||||||
$source = %s;
|
$source = %s;
|
||||||
$buffer .= $this->mustache
|
$buffer .= $this->mustache
|
||||||
->loadLambda((string) call_user_func($value, $source)%s)
|
->loadLambda((string) call_user_func($value, $source, $this->lambdaHelper)%s)
|
||||||
->renderInternal($context, $indent);
|
->renderInternal($context, $indent);
|
||||||
} elseif (!empty($value)) {
|
} elseif (!empty($value)) {
|
||||||
$values = $this->isIterable($value) ? $value : array($value);
|
$values = $this->isIterable($value) ? $value : array($value);
|
||||||
@@ -260,7 +269,7 @@ class Mustache_Compiler
|
|||||||
$value = $this->mustache
|
$value = $this->mustache
|
||||||
->loadLambda((string) call_user_func($value))
|
->loadLambda((string) call_user_func($value))
|
||||||
->renderInternal($context, $indent);
|
->renderInternal($context, $indent);
|
||||||
}
|
}%s
|
||||||
$buffer .= %s%s;
|
$buffer .= %s%s;
|
||||||
';
|
';
|
||||||
|
|
||||||
@@ -275,11 +284,63 @@ class Mustache_Compiler
|
|||||||
*/
|
*/
|
||||||
private function variable($id, $escape, $level)
|
private function variable($id, $escape, $level)
|
||||||
{
|
{
|
||||||
|
$filters = '';
|
||||||
|
|
||||||
|
if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
|
||||||
|
list($id, $filters) = $this->getFilters($id, $level);
|
||||||
|
}
|
||||||
|
|
||||||
$method = $this->getFindMethod($id);
|
$method = $this->getFindMethod($id);
|
||||||
$id = ($method !== 'last') ? var_export($id, true) : '';
|
$id = ($method !== 'last') ? var_export($id, true) : '';
|
||||||
$value = $escape ? $this->getEscape() : '$value';
|
$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, $filters, $this->flushIndent(), $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate Mustache Template variable filtering PHP source.
|
||||||
|
*
|
||||||
|
* @param string $id Variable name
|
||||||
|
* @param int $level
|
||||||
|
*
|
||||||
|
* @return string Generated variable filtering PHP source
|
||||||
|
*/
|
||||||
|
private function getFilters($id, $level)
|
||||||
|
{
|
||||||
|
$filters = array_map('trim', explode('|', $id));
|
||||||
|
$id = array_shift($filters);
|
||||||
|
|
||||||
|
return array($id, $this->getFilter($filters, $level));
|
||||||
|
}
|
||||||
|
|
||||||
|
const FILTER = '
|
||||||
|
$filter = $context->%s(%s);
|
||||||
|
if (is_string($filter) || !is_callable($filter)) {
|
||||||
|
throw new UnexpectedValueException(%s);
|
||||||
|
}
|
||||||
|
$value = call_user_func($filter, $value);%s
|
||||||
|
';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate PHP source for a single filter.
|
||||||
|
*
|
||||||
|
* @param array $filters
|
||||||
|
* @param int $level
|
||||||
|
*
|
||||||
|
* @return string Generated filter PHP source
|
||||||
|
*/
|
||||||
|
private function getFilter(array $filters, $level)
|
||||||
|
{
|
||||||
|
if (empty($filters)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = array_shift($filters);
|
||||||
|
$method = $this->getFindMethod($name);
|
||||||
|
$filter = ($method !== 'last') ? var_export($name, true) : '';
|
||||||
|
$msg = var_export(sprintf('Filter not found: %s', $name), true);
|
||||||
|
|
||||||
|
return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $msg, $this->getFilter($filters, $level));
|
||||||
}
|
}
|
||||||
|
|
||||||
const LINE = '$buffer .= "\n";';
|
const LINE = '$buffer .= "\n";';
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class Mustache_Context
|
|||||||
private function findVariableInStack($id, array $stack)
|
private function findVariableInStack($id, array $stack)
|
||||||
{
|
{
|
||||||
for ($i = count($stack) - 1; $i >= 0; $i--) {
|
for ($i = count($stack) - 1; $i >= 0; $i--) {
|
||||||
if (is_object($stack[$i])) {
|
if (is_object($stack[$i]) && !$stack[$i] instanceof Closure) {
|
||||||
if (method_exists($stack[$i], $id)) {
|
if (method_exists($stack[$i], $id)) {
|
||||||
return $stack[$i]->$id();
|
return $stack[$i]->$id();
|
||||||
} elseif (isset($stack[$i]->$id)) {
|
} elseif (isset($stack[$i]->$id)) {
|
||||||
|
|||||||
+122
-10
@@ -23,20 +23,24 @@
|
|||||||
*/
|
*/
|
||||||
class Mustache_Engine
|
class Mustache_Engine
|
||||||
{
|
{
|
||||||
const VERSION = '2.0.2';
|
const VERSION = '2.1.0';
|
||||||
const SPEC_VERSION = '1.1.2';
|
const SPEC_VERSION = '1.1.2';
|
||||||
|
|
||||||
|
const PRAGMA_FILTERS = 'FILTERS';
|
||||||
|
|
||||||
// Template cache
|
// Template cache
|
||||||
private $templates = array();
|
private $templates = array();
|
||||||
|
|
||||||
// Environment
|
// Environment
|
||||||
private $templateClassPrefix = '__Mustache_';
|
private $templateClassPrefix = '__Mustache_';
|
||||||
private $cache = null;
|
private $cache = null;
|
||||||
|
private $cacheFileMode = null;
|
||||||
private $loader;
|
private $loader;
|
||||||
private $partialsLoader;
|
private $partialsLoader;
|
||||||
private $helpers;
|
private $helpers;
|
||||||
private $escape;
|
private $escape;
|
||||||
private $charset = 'UTF-8';
|
private $charset = 'UTF-8';
|
||||||
|
private $logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mustache class constructor.
|
* Mustache class constructor.
|
||||||
@@ -44,13 +48,17 @@ class Mustache_Engine
|
|||||||
* Passing an $options array allows overriding certain Mustache options during instantiation:
|
* Passing an $options array allows overriding certain Mustache options during instantiation:
|
||||||
*
|
*
|
||||||
* $options = array(
|
* $options = array(
|
||||||
* // The class prefix for compiled templates. Defaults to '__Mustache_'
|
* // The class prefix for compiled templates. Defaults to '__Mustache_'.
|
||||||
* 'template_class_prefix' => '__MyTemplates_',
|
* 'template_class_prefix' => '__MyTemplates_',
|
||||||
*
|
*
|
||||||
* // A cache directory for compiled templates. Mustache will not cache templates unless this is set
|
* // A cache directory for compiled templates. Mustache will not cache templates unless this is set
|
||||||
* 'cache' => dirname(__FILE__).'/tmp/cache/mustache',
|
* 'cache' => dirname(__FILE__).'/tmp/cache/mustache',
|
||||||
*
|
*
|
||||||
* // A Mustache template loader instance. Uses a StringLoader if not specified
|
* // Override default permissions for cache files. Defaults to using the system-defined umask. It is
|
||||||
|
* // *strongly* recommended that you configure your umask properly rather than overriding permissions here.
|
||||||
|
* 'cache_file_mode' => 0666,
|
||||||
|
*
|
||||||
|
* // A Mustache template loader instance. Uses a StringLoader if not specified.
|
||||||
* 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
|
* 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
|
||||||
*
|
*
|
||||||
* // A Mustache loader instance for partials.
|
* // A Mustache loader instance for partials.
|
||||||
@@ -72,8 +80,13 @@ class Mustache_Engine
|
|||||||
* return htmlspecialchars($buffer, ENT_COMPAT, 'UTF-8');
|
* return htmlspecialchars($buffer, ENT_COMPAT, 'UTF-8');
|
||||||
* },
|
* },
|
||||||
*
|
*
|
||||||
* // character set for `htmlspecialchars`. Defaults to 'UTF-8'
|
* // Character set for `htmlspecialchars`. Defaults to 'UTF-8'. Use 'UTF-8'.
|
||||||
* 'charset' => 'ISO-8859-1',
|
* 'charset' => 'ISO-8859-1',
|
||||||
|
*
|
||||||
|
* // A Mustache Logger instance. No logging will occur unless this is set. Using a PSR-3 compatible
|
||||||
|
* // logging library -- such as Monolog -- is highly recommended. A simple stream logger implementation is
|
||||||
|
* // available as well:
|
||||||
|
* 'logger' => new Mustache_StreamLogger('php://stderr'),
|
||||||
* );
|
* );
|
||||||
*
|
*
|
||||||
* @param array $options (default: array())
|
* @param array $options (default: array())
|
||||||
@@ -88,6 +101,10 @@ class Mustache_Engine
|
|||||||
$this->cache = $options['cache'];
|
$this->cache = $options['cache'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($options['cache_file_mode'])) {
|
||||||
|
$this->cacheFileMode = $options['cache_file_mode'];
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($options['loader'])) {
|
if (isset($options['loader'])) {
|
||||||
$this->setLoader($options['loader']);
|
$this->setLoader($options['loader']);
|
||||||
}
|
}
|
||||||
@@ -115,6 +132,10 @@ class Mustache_Engine
|
|||||||
if (isset($options['charset'])) {
|
if (isset($options['charset'])) {
|
||||||
$this->charset = $options['charset'];
|
$this->charset = $options['charset'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($options['logger'])) {
|
||||||
|
$this->setLogger($options['logger']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -319,6 +340,30 @@ class Mustache_Engine
|
|||||||
$this->getHelpers()->remove($name);
|
$this->getHelpers()->remove($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the Mustache Logger instance.
|
||||||
|
*
|
||||||
|
* @param Mustache_Logger|Psr\Log\LoggerInterface $logger
|
||||||
|
*/
|
||||||
|
public function setLogger($logger = null)
|
||||||
|
{
|
||||||
|
if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) {
|
||||||
|
throw new InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current Mustache Logger instance.
|
||||||
|
*
|
||||||
|
* @return Mustache_Logger|Psr\Log\LoggerInterface
|
||||||
|
*/
|
||||||
|
public function getLogger()
|
||||||
|
{
|
||||||
|
return $this->logger;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the Mustache Tokenizer instance.
|
* Set the Mustache Tokenizer instance.
|
||||||
*
|
*
|
||||||
@@ -442,7 +487,12 @@ class Mustache_Engine
|
|||||||
try {
|
try {
|
||||||
return $this->loadSource($this->getPartialsLoader()->load($name));
|
return $this->loadSource($this->getPartialsLoader()->load($name));
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
// If the named partial cannot be found, return null.
|
// If the named partial cannot be found, log then return null.
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::WARNING,
|
||||||
|
'Partial not found: "{name}"',
|
||||||
|
array('name' => $name)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,15 +535,33 @@ class Mustache_Engine
|
|||||||
if (!class_exists($className, false)) {
|
if (!class_exists($className, false)) {
|
||||||
if ($fileName = $this->getCacheFilename($source)) {
|
if ($fileName = $this->getCacheFilename($source)) {
|
||||||
if (!is_file($fileName)) {
|
if (!is_file($fileName)) {
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::DEBUG,
|
||||||
|
'Writing "{className}" class to template cache: "{fileName}"',
|
||||||
|
array('className' => $className, 'fileName' => $fileName)
|
||||||
|
);
|
||||||
|
|
||||||
$this->writeCacheFile($fileName, $this->compile($source));
|
$this->writeCacheFile($fileName, $this->compile($source));
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once $fileName;
|
require_once $fileName;
|
||||||
} else {
|
} else {
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::WARNING,
|
||||||
|
'Template cache disabled, evaluating "{className}" class at runtime',
|
||||||
|
array('className' => $className)
|
||||||
|
);
|
||||||
|
|
||||||
eval('?>'.$this->compile($source));
|
eval('?>'.$this->compile($source));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::DEBUG,
|
||||||
|
'Instantiating template: "{className}"',
|
||||||
|
array('className' => $className)
|
||||||
|
);
|
||||||
|
|
||||||
$this->templates[$className] = new $className($this);
|
$this->templates[$className] = new $className($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,6 +610,12 @@ class Mustache_Engine
|
|||||||
$tree = $this->parse($source);
|
$tree = $this->parse($source);
|
||||||
$name = $this->getTemplateClassName($source);
|
$name = $this->getTemplateClassName($source);
|
||||||
|
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::INFO,
|
||||||
|
'Compiling template to "{className}" class',
|
||||||
|
array('className' => $name)
|
||||||
|
);
|
||||||
|
|
||||||
return $this->getCompiler()->compile($source, $tree, $name, isset($this->escape), $this->charset);
|
return $this->getCompiler()->compile($source, $tree, $name, isset($this->escape), $this->charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +636,7 @@ class Mustache_Engine
|
|||||||
/**
|
/**
|
||||||
* Helper method to dump a generated Mustache Template subclass to the file cache.
|
* Helper method to dump a generated Mustache Template subclass to the file cache.
|
||||||
*
|
*
|
||||||
* @throws RuntimeException if unable to write to $fileName.
|
* @throws RuntimeException if unable to create the cache directory or write to $fileName.
|
||||||
*
|
*
|
||||||
* @param string $fileName
|
* @param string $fileName
|
||||||
* @param string $source
|
* @param string $source
|
||||||
@@ -571,19 +645,57 @@ class Mustache_Engine
|
|||||||
*/
|
*/
|
||||||
private function writeCacheFile($fileName, $source)
|
private function writeCacheFile($fileName, $source)
|
||||||
{
|
{
|
||||||
if (!is_dir(dirname($fileName))) {
|
$dirName = dirname($fileName);
|
||||||
mkdir(dirname($fileName), 0777, true);
|
if (!is_dir($dirName)) {
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::INFO,
|
||||||
|
'Creating Mustache template cache directory: "{dirName}"',
|
||||||
|
array('dirName' => $dirName)
|
||||||
|
);
|
||||||
|
|
||||||
|
@mkdir($dirName, 0777, true);
|
||||||
|
if (!is_dir($dirName)) {
|
||||||
|
throw new RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName));
|
||||||
}
|
}
|
||||||
|
|
||||||
$tempFile = tempnam(dirname($fileName), basename($fileName));
|
}
|
||||||
|
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::DEBUG,
|
||||||
|
'Caching compiled template to "{fileName}"',
|
||||||
|
array('fileName' => $fileName)
|
||||||
|
);
|
||||||
|
|
||||||
|
$tempFile = tempnam($dirName, basename($fileName));
|
||||||
if (false !== @file_put_contents($tempFile, $source)) {
|
if (false !== @file_put_contents($tempFile, $source)) {
|
||||||
if (@rename($tempFile, $fileName)) {
|
if (@rename($tempFile, $fileName)) {
|
||||||
chmod($fileName, 0644);
|
$mode = isset($this->cacheFileMode) ? $this->cacheFileMode : (0666 & ~umask());
|
||||||
|
@chmod($fileName, $mode);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->log(
|
||||||
|
Mustache_Logger::ERROR,
|
||||||
|
'Unable to rename Mustache temp cache file: "{tempName}" -> "{fileName}"',
|
||||||
|
array('tempName' => $tempFile, 'fileName' => $fileName)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException(sprintf('Failed to write cache file "%s".', $fileName));
|
throw new RuntimeException(sprintf('Failed to write cache file "%s".', $fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a log record if logging is enabled.
|
||||||
|
*
|
||||||
|
* @param integer $level The logging level
|
||||||
|
* @param string $message The log message
|
||||||
|
* @param array $context The log context
|
||||||
|
*/
|
||||||
|
private function log($level, $message, array $context = array())
|
||||||
|
{
|
||||||
|
if (isset($this->logger)) {
|
||||||
|
$this->logger->log($level, $message, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mustache Lambda Helper.
|
||||||
|
*
|
||||||
|
* Passed to section and interpolation lambdas, giving them access to a `render`
|
||||||
|
* method for rendering a string with the current context.
|
||||||
|
*/
|
||||||
|
class Mustache_LambdaHelper
|
||||||
|
{
|
||||||
|
private $mustache;
|
||||||
|
private $context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mustache Lambda Helper constructor.
|
||||||
|
*
|
||||||
|
* @param Mustache_Engine $mustache Mustache engine instance.
|
||||||
|
* @param Mustache_Context $context Rendering context.
|
||||||
|
*/
|
||||||
|
public function __construct(Mustache_Engine $mustache, Mustache_Context $context)
|
||||||
|
{
|
||||||
|
$this->mustache = $mustache;
|
||||||
|
$this->context = $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a string as a Mustache template with the current rendering context.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return Rendered template.
|
||||||
|
*/
|
||||||
|
public function render($string)
|
||||||
|
{
|
||||||
|
return $this->mustache
|
||||||
|
->loadLambda((string) $string)
|
||||||
|
->renderInternal($this->context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,19 +12,19 @@
|
|||||||
/**
|
/**
|
||||||
* Mustache Template filesystem Loader implementation.
|
* Mustache Template filesystem Loader implementation.
|
||||||
*
|
*
|
||||||
* An ArrayLoader instance loads Mustache Template source from the filesystem by name:
|
* A FilesystemLoader instance loads Mustache Template source from the filesystem by name:
|
||||||
*
|
*
|
||||||
* $loader = new FilesystemLoader(dirname(__FILE__).'/views');
|
* $loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views');
|
||||||
* $tpl = $loader->load('foo'); // equivalent to `file_get_contents(dirname(__FILE__).'/views/foo.mustache');
|
* $tpl = $loader->load('foo'); // equivalent to `file_get_contents(dirname(__FILE__).'/views/foo.mustache');
|
||||||
*
|
*
|
||||||
* This is probably the most useful Mustache Loader implementation. It can be used for partials and normal Templates:
|
* This is probably the most useful Mustache Loader implementation. It can be used for partials and normal Templates:
|
||||||
*
|
*
|
||||||
* $m = new Mustache(array(
|
* $m = new Mustache(array(
|
||||||
* 'loader' => new FilesystemLoader(dirname(__FILE__).'/views'),
|
* 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
|
||||||
* 'partials_loader' => new FilesystemLoader(dirname(__FILE__).'/views/partials'),
|
* 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views/partials'),
|
||||||
* ));
|
* ));
|
||||||
*
|
*
|
||||||
* @implements Loader
|
* @implements Mustache_Loader
|
||||||
*/
|
*/
|
||||||
class Mustache_Loader_FilesystemLoader implements Mustache_Loader
|
class Mustache_Loader_FilesystemLoader implements Mustache_Loader
|
||||||
{
|
{
|
||||||
@@ -55,15 +55,19 @@ class Mustache_Loader_FilesystemLoader implements Mustache_Loader
|
|||||||
throw new RuntimeException('FilesystemLoader baseDir must be a directory: '.$baseDir);
|
throw new RuntimeException('FilesystemLoader baseDir must be a directory: '.$baseDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($options['extension'])) {
|
if (array_key_exists('extension', $options)) {
|
||||||
|
if (empty($options['extension'])) {
|
||||||
|
$this->extension = '';
|
||||||
|
} else {
|
||||||
$this->extension = '.' . ltrim($options['extension'], '.');
|
$this->extension = '.' . ltrim($options['extension'], '.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a Template by name.
|
* Load a Template by name.
|
||||||
*
|
*
|
||||||
* $loader = new FilesystemLoader(dirname(__FILE__).'/views');
|
* $loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views');
|
||||||
* $loader->load('admin/dashboard'); // loads "./views/admin/dashboard.mustache";
|
* $loader->load('admin/dashboard'); // loads "./views/admin/dashboard.mustache";
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a Mustache logger instance
|
||||||
|
*
|
||||||
|
* This is identical to the Psr\Log\LoggerInterface.
|
||||||
|
*
|
||||||
|
* The message MUST be a string or object implementing __toString().
|
||||||
|
*
|
||||||
|
* The message MAY contain placeholders in the form: {foo} where foo
|
||||||
|
* will be replaced by the context data in key "foo".
|
||||||
|
*
|
||||||
|
* The context array can contain arbitrary data, the only assumption that
|
||||||
|
* can be made by implementors is that if an Exception instance is given
|
||||||
|
* to produce a stack trace, it MUST be in a key named "exception".
|
||||||
|
*
|
||||||
|
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
|
||||||
|
* for the full interface specification.
|
||||||
|
*/
|
||||||
|
interface Mustache_Logger
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Psr\Log compatible log levels
|
||||||
|
*/
|
||||||
|
const EMERGENCY = 'emergency';
|
||||||
|
const ALERT = 'alert';
|
||||||
|
const CRITICAL = 'critical';
|
||||||
|
const ERROR = 'error';
|
||||||
|
const WARNING = 'warning';
|
||||||
|
const NOTICE = 'notice';
|
||||||
|
const INFO = 'info';
|
||||||
|
const DEBUG = 'debug';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System is unusable.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function emergency($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action must be taken immediately.
|
||||||
|
*
|
||||||
|
* Example: Entire website down, database unavailable, etc. This should
|
||||||
|
* trigger the SMS alerts and wake you up.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function alert($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Critical conditions.
|
||||||
|
*
|
||||||
|
* Example: Application component unavailable, unexpected exception.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function critical($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime errors that do not require immediate action but should typically
|
||||||
|
* be logged and monitored.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function error($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exceptional occurrences that are not errors.
|
||||||
|
*
|
||||||
|
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||||
|
* that are not necessarily wrong.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function warning($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal but significant events.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function notice($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interesting events.
|
||||||
|
*
|
||||||
|
* Example: User logs in, SQL logs.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function info($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detailed debug information.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function debug($message, array $context = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs with an arbitrary level.
|
||||||
|
*
|
||||||
|
* @param mixed $level
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function log($level, $message, array $context = array());
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a simple Logger implementation that other Loggers can inherit from.
|
||||||
|
*
|
||||||
|
* This is identical to the Psr\Log\AbstractLogger.
|
||||||
|
*
|
||||||
|
* It simply delegates all log-level-specific methods to the `log` method to
|
||||||
|
* reduce boilerplate code that a simple Logger that does the same thing with
|
||||||
|
* messages regardless of the error level has to implement.
|
||||||
|
*/
|
||||||
|
abstract class Mustache_Logger_AbstractLogger implements Mustache_Logger
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* System is unusable.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function emergency($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::EMERGENCY, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action must be taken immediately.
|
||||||
|
*
|
||||||
|
* Example: Entire website down, database unavailable, etc. This should
|
||||||
|
* trigger the SMS alerts and wake you up.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function alert($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::ALERT, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Critical conditions.
|
||||||
|
*
|
||||||
|
* Example: Application component unavailable, unexpected exception.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function critical($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::CRITICAL, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime errors that do not require immediate action but should typically
|
||||||
|
* be logged and monitored.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function error($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::ERROR, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exceptional occurrences that are not errors.
|
||||||
|
*
|
||||||
|
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||||
|
* that are not necessarily wrong.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function warning($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::WARNING, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal but significant events.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function notice($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::NOTICE, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interesting events.
|
||||||
|
*
|
||||||
|
* Example: User logs in, SQL logs.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function info($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::INFO, $message, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detailed debug information.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function debug($message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log(Mustache_Logger::DEBUG, $message, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Mustache Stream Logger.
|
||||||
|
*
|
||||||
|
* The Stream Logger wraps a file resource instance (such as a stream) or a
|
||||||
|
* stream URL. All log messages over the threshold level will be appended to
|
||||||
|
* this stream.
|
||||||
|
*
|
||||||
|
* Hint: Try `php://stderr` for your stream URL.
|
||||||
|
*/
|
||||||
|
class Mustache_Logger_StreamLogger extends Mustache_Logger_AbstractLogger
|
||||||
|
{
|
||||||
|
protected static $levels = array(
|
||||||
|
self::DEBUG => 100,
|
||||||
|
self::INFO => 200,
|
||||||
|
self::NOTICE => 250,
|
||||||
|
self::WARNING => 300,
|
||||||
|
self::ERROR => 400,
|
||||||
|
self::CRITICAL => 500,
|
||||||
|
self::ALERT => 550,
|
||||||
|
self::EMERGENCY => 600,
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $stream = null;
|
||||||
|
protected $url = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws InvalidArgumentException if the logging level is unknown.
|
||||||
|
*
|
||||||
|
* @param string $stream Resource instance or URL
|
||||||
|
* @param integer $level The minimum logging level at which this handler will be triggered
|
||||||
|
*/
|
||||||
|
public function __construct($stream, $level = Mustache_Logger::ERROR)
|
||||||
|
{
|
||||||
|
$this->setLevel($level);
|
||||||
|
|
||||||
|
if (is_resource($stream)) {
|
||||||
|
$this->stream = $stream;
|
||||||
|
} else {
|
||||||
|
$this->url = $stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close stream resources.
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if (is_resource($this->stream)) {
|
||||||
|
fclose($this->stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimum logging level.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException if the logging level is unknown.
|
||||||
|
*
|
||||||
|
* @param integer $level The minimum logging level which will be written
|
||||||
|
*/
|
||||||
|
public function setLevel($level)
|
||||||
|
{
|
||||||
|
if (!array_key_exists($level, self::$levels)) {
|
||||||
|
throw new InvalidArgumentException('Unexpected logging level: ' . $level);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->level = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current minimum logging level.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLevel()
|
||||||
|
{
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs with an arbitrary level.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException if the logging level is unknown.
|
||||||
|
*
|
||||||
|
* @param mixed $level
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function log($level, $message, array $context = array())
|
||||||
|
{
|
||||||
|
if (!array_key_exists($level, self::$levels)) {
|
||||||
|
throw new InvalidArgumentException('Unexpected logging level: ' . $level);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$levels[$level] >= self::$levels[$this->level]) {
|
||||||
|
$this->writeLog($level, $message, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a record to the log.
|
||||||
|
*
|
||||||
|
* @param integer $level The logging level
|
||||||
|
* @param string $message The log message
|
||||||
|
* @param array $context The log context
|
||||||
|
*/
|
||||||
|
protected function writeLog($level, $message, array $context = array())
|
||||||
|
{
|
||||||
|
if (!is_resource($this->stream)) {
|
||||||
|
if (!isset($this->url)) {
|
||||||
|
throw new LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stream = fopen($this->url, 'a');
|
||||||
|
if (!is_resource($this->stream)) {
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
throw new UnexpectedValueException(sprintf('The stream or file "%s" could not be opened.', $this->url));
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($this->stream, self::formatLine($level, $message, $context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the logging level.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException if the logging level is unknown.
|
||||||
|
*
|
||||||
|
* @param integer $level
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function getLevelName($level)
|
||||||
|
{
|
||||||
|
return strtoupper($level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a log line for output.
|
||||||
|
*
|
||||||
|
* @param integer $level The logging level
|
||||||
|
* @param string $message The log message
|
||||||
|
* @param array $context The log context
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function formatLine($level, $message, array $context = array())
|
||||||
|
{
|
||||||
|
return sprintf(
|
||||||
|
"%s: %s\n",
|
||||||
|
self::getLevelName($level),
|
||||||
|
self::interpolateMessage($message, $context)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpolate context values into the message placeholders.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function interpolateMessage($message, array $context = array())
|
||||||
|
{
|
||||||
|
$message = (string) $message;
|
||||||
|
|
||||||
|
// build a replacement array with braces around the context keys
|
||||||
|
$replace = array();
|
||||||
|
foreach ($context as $key => $val) {
|
||||||
|
$replace['{' . $key . '}'] = $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// interpolate replacement values into the the message and return
|
||||||
|
return strtr($message, $replace);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ class Mustache_Tokenizer
|
|||||||
const T_UNESCAPED = '{';
|
const T_UNESCAPED = '{';
|
||||||
const T_UNESCAPED_2 = '&';
|
const T_UNESCAPED_2 = '&';
|
||||||
const T_TEXT = '_t';
|
const T_TEXT = '_t';
|
||||||
|
const T_PRAGMA = '%';
|
||||||
|
|
||||||
// Valid token types
|
// Valid token types
|
||||||
private static $tagTypes = array(
|
private static $tagTypes = array(
|
||||||
@@ -47,6 +48,7 @@ class Mustache_Tokenizer
|
|||||||
self::T_ESCAPED => true,
|
self::T_ESCAPED => true,
|
||||||
self::T_UNESCAPED => true,
|
self::T_UNESCAPED => true,
|
||||||
self::T_UNESCAPED_2 => true,
|
self::T_UNESCAPED_2 => true,
|
||||||
|
self::T_PRAGMA => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Interpolated tags
|
// Interpolated tags
|
||||||
@@ -67,6 +69,7 @@ class Mustache_Tokenizer
|
|||||||
const NODES = 'nodes';
|
const NODES = 'nodes';
|
||||||
const VALUE = 'value';
|
const VALUE = 'value';
|
||||||
|
|
||||||
|
private $pragmas;
|
||||||
private $state;
|
private $state;
|
||||||
private $tagType;
|
private $tagType;
|
||||||
private $tag;
|
private $tag;
|
||||||
@@ -126,6 +129,9 @@ class Mustache_Tokenizer
|
|||||||
if ($this->tagType === self::T_DELIM_CHANGE) {
|
if ($this->tagType === self::T_DELIM_CHANGE) {
|
||||||
$i = $this->changeDelimiters($text, $i);
|
$i = $this->changeDelimiters($text, $i);
|
||||||
$this->state = self::IN_TEXT;
|
$this->state = self::IN_TEXT;
|
||||||
|
} elseif ($this->tagType === self::T_PRAGMA) {
|
||||||
|
$i = $this->addPragma($text, $i);
|
||||||
|
$this->state = self::IN_TEXT;
|
||||||
} else {
|
} else {
|
||||||
if ($tag !== null) {
|
if ($tag !== null) {
|
||||||
$i++;
|
$i++;
|
||||||
@@ -168,6 +174,13 @@ class Mustache_Tokenizer
|
|||||||
|
|
||||||
$this->filterLine(true);
|
$this->filterLine(true);
|
||||||
|
|
||||||
|
foreach ($this->pragmas as $pragma) {
|
||||||
|
array_unshift($this->tokens, array(
|
||||||
|
self::TYPE => self::T_PRAGMA,
|
||||||
|
self::NAME => $pragma,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return $this->tokens;
|
return $this->tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +198,7 @@ class Mustache_Tokenizer
|
|||||||
$this->lineStart = 0;
|
$this->lineStart = 0;
|
||||||
$this->otag = '{{';
|
$this->otag = '{{';
|
||||||
$this->ctag = '}}';
|
$this->ctag = '}}';
|
||||||
|
$this->pragmas = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -270,6 +284,14 @@ class Mustache_Tokenizer
|
|||||||
return $closeIndex + strlen($close) - 1;
|
return $closeIndex + strlen($close) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function addPragma($text, $index)
|
||||||
|
{
|
||||||
|
$end = strpos($text, $this->ctag, $index);
|
||||||
|
$this->pragmas[] = trim(substr($text, $index + 2, $end - $index - 2));
|
||||||
|
|
||||||
|
return $end + strlen($this->ctag) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether it's time to change tags.
|
* Test whether it's time to change tags.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -27,11 +27,14 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testConstructor()
|
public function testConstructor()
|
||||||
{
|
{
|
||||||
|
$logger = new Mustache_Logger_StreamLogger(tmpfile());
|
||||||
$loader = new Mustache_Loader_StringLoader;
|
$loader = new Mustache_Loader_StringLoader;
|
||||||
$partialsLoader = new Mustache_Loader_ArrayLoader;
|
$partialsLoader = new Mustache_Loader_ArrayLoader;
|
||||||
$mustache = new Mustache_Engine(array(
|
$mustache = new Mustache_Engine(array(
|
||||||
'template_class_prefix' => '__whot__',
|
'template_class_prefix' => '__whot__',
|
||||||
'cache' => self::$tempDir,
|
'cache' => self::$tempDir,
|
||||||
|
'cache_file_mode' => 777,
|
||||||
|
'logger' => $logger,
|
||||||
'loader' => $loader,
|
'loader' => $loader,
|
||||||
'partials_loader' => $partialsLoader,
|
'partials_loader' => $partialsLoader,
|
||||||
'partials' => array(
|
'partials' => array(
|
||||||
@@ -45,6 +48,7 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase
|
|||||||
'charset' => 'ISO-8859-1',
|
'charset' => 'ISO-8859-1',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->assertSame($logger, $mustache->getLogger());
|
||||||
$this->assertSame($loader, $mustache->getLoader());
|
$this->assertSame($loader, $mustache->getLoader());
|
||||||
$this->assertSame($partialsLoader, $mustache->getPartialsLoader());
|
$this->assertSame($partialsLoader, $mustache->getPartialsLoader());
|
||||||
$this->assertEquals('{{ foo }}', $partialsLoader->load('foo'));
|
$this->assertEquals('{{ foo }}', $partialsLoader->load('foo'));
|
||||||
@@ -85,12 +89,17 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testSettingServices()
|
public function testSettingServices()
|
||||||
{
|
{
|
||||||
|
$logger = new Mustache_Logger_StreamLogger(tmpfile());
|
||||||
$loader = new Mustache_Loader_StringLoader;
|
$loader = new Mustache_Loader_StringLoader;
|
||||||
$tokenizer = new Mustache_Tokenizer;
|
$tokenizer = new Mustache_Tokenizer;
|
||||||
$parser = new Mustache_Parser;
|
$parser = new Mustache_Parser;
|
||||||
$compiler = new Mustache_Compiler;
|
$compiler = new Mustache_Compiler;
|
||||||
$mustache = new Mustache_Engine;
|
$mustache = new Mustache_Engine;
|
||||||
|
|
||||||
|
$this->assertNotSame($logger, $mustache->getLogger());
|
||||||
|
$mustache->setLogger($logger);
|
||||||
|
$this->assertSame($logger, $mustache->getLogger());
|
||||||
|
|
||||||
$this->assertNotSame($loader, $mustache->getLoader());
|
$this->assertNotSame($loader, $mustache->getLoader());
|
||||||
$mustache->setLoader($loader);
|
$mustache->setLoader($loader);
|
||||||
$this->assertSame($loader, $mustache->getLoader());
|
$this->assertSame($loader, $mustache->getLoader());
|
||||||
@@ -222,6 +231,74 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase
|
|||||||
$mustache->setHelpers('monkeymonkeymonkey');
|
$mustache->setHelpers('monkeymonkeymonkey');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testSetLoggerThrowsExceptions()
|
||||||
|
{
|
||||||
|
$mustache = new Mustache_Engine;
|
||||||
|
$mustache->setLogger(new StdClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPartialLoadFailLogging()
|
||||||
|
{
|
||||||
|
$name = tempnam(sys_get_temp_dir(), 'mustache-test');
|
||||||
|
$mustache = new Mustache_Engine(array(
|
||||||
|
'logger' => new Mustache_Logger_StreamLogger($name, Mustache_Logger::WARNING),
|
||||||
|
'partials' => array(
|
||||||
|
'foo' => 'FOO',
|
||||||
|
'bar' => 'BAR',
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$result = $mustache->render('{{> foo }}{{> bar }}{{> baz }}', array());
|
||||||
|
$this->assertEquals('FOOBAR', $result);
|
||||||
|
|
||||||
|
$this->assertContains('WARNING: Partial not found: "baz"', file_get_contents($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCacheWarningLogging()
|
||||||
|
{
|
||||||
|
$name = tempnam(sys_get_temp_dir(), 'mustache-test');
|
||||||
|
$mustache = new Mustache_Engine(array(
|
||||||
|
'logger' => new Mustache_Logger_StreamLogger($name, Mustache_Logger::WARNING)
|
||||||
|
));
|
||||||
|
|
||||||
|
$result = $mustache->render('{{ foo }}', array('foo' => 'FOO'));
|
||||||
|
$this->assertEquals('FOO', $result);
|
||||||
|
|
||||||
|
$this->assertContains('WARNING: Template cache disabled, evaluating', file_get_contents($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoggingIsNotTooAnnoying()
|
||||||
|
{
|
||||||
|
$name = tempnam(sys_get_temp_dir(), 'mustache-test');
|
||||||
|
$mustache = new Mustache_Engine(array(
|
||||||
|
'logger' => new Mustache_Logger_StreamLogger($name)
|
||||||
|
));
|
||||||
|
|
||||||
|
$result = $mustache->render('{{ foo }}{{> bar }}', array('foo' => 'FOO'));
|
||||||
|
$this->assertEquals('FOO', $result);
|
||||||
|
|
||||||
|
$this->assertEmpty(file_get_contents($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testVerboseLoggingIsVerbose()
|
||||||
|
{
|
||||||
|
$name = tempnam(sys_get_temp_dir(), 'mustache-test');
|
||||||
|
$mustache = new Mustache_Engine(array(
|
||||||
|
'logger' => new Mustache_Logger_StreamLogger($name, Mustache_Logger::DEBUG)
|
||||||
|
));
|
||||||
|
|
||||||
|
$result = $mustache->render('{{ foo }}{{> bar }}', array('foo' => 'FOO'));
|
||||||
|
$this->assertEquals('FOO', $result);
|
||||||
|
|
||||||
|
$log = file_get_contents($name);
|
||||||
|
|
||||||
|
$this->assertContains("DEBUG: Instantiating template: ", $log);
|
||||||
|
$this->assertContains("WARNING: Partial not found: \"bar\"", $log);
|
||||||
|
}
|
||||||
|
|
||||||
private static function rmdir($path)
|
private static function rmdir($path)
|
||||||
{
|
{
|
||||||
$path = rtrim($path, '/').'/';
|
$path = rtrim($path, '/').'/';
|
||||||
@@ -244,7 +321,8 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MustacheStub extends Mustache_Engine {
|
class MustacheStub extends Mustache_Engine
|
||||||
|
{
|
||||||
public $source;
|
public $source;
|
||||||
public $template;
|
public $template;
|
||||||
public function loadTemplate($source)
|
public function loadTemplate($source)
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group lambdas
|
||||||
|
* @group functional
|
||||||
|
*/
|
||||||
|
class Mustache_Test_FiveThree_Functional_ClosuresQuirksTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
private $mustache;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->mustache = new Mustache_Engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClosuresDontLikeItWhenYouTouchTheirProperties()
|
||||||
|
{
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{ foo.bar }}');
|
||||||
|
$this->assertEquals('', $tpl->render(array('foo' => function() { return 'FOO'; })));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group filters
|
||||||
|
* @group functional
|
||||||
|
*/
|
||||||
|
class Mustache_Test_FiveThree_Functional_FiltersTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
private $mustache;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->mustache = new Mustache_Engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleFilter()
|
||||||
|
{
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{% FILTERS }}{{ date | longdate }}');
|
||||||
|
|
||||||
|
$this->mustache->addHelper('longdate', function(\DateTime $value) {
|
||||||
|
return $value->format('Y-m-d h:m:s');
|
||||||
|
});
|
||||||
|
|
||||||
|
$foo = new \StdClass;
|
||||||
|
$foo->date = new DateTime('1/1/2000');
|
||||||
|
|
||||||
|
$this->assertEquals('2000-01-01 12:01:00', $tpl->render($foo));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChainedFilters()
|
||||||
|
{
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{% FILTERS }}{{ date | longdate | withbrackets }}');
|
||||||
|
|
||||||
|
$this->mustache->addHelper('longdate', function(\DateTime $value) {
|
||||||
|
return $value->format('Y-m-d h:m:s');
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->mustache->addHelper('withbrackets', function($value) {
|
||||||
|
return sprintf('[[%s]]', $value);
|
||||||
|
});
|
||||||
|
|
||||||
|
$foo = new \StdClass;
|
||||||
|
$foo->date = new DateTime('1/1/2000');
|
||||||
|
|
||||||
|
$this->assertEquals('[[2000-01-01 12:01:00]]', $tpl->render($foo));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInterpolateFirst()
|
||||||
|
{
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{% FILTERS }}{{ foo | bar }}');
|
||||||
|
$this->assertEquals('win!', $tpl->render(array(
|
||||||
|
'foo' => 'FOO',
|
||||||
|
'bar' => function($value) {
|
||||||
|
return ($value === 'FOO') ? 'win!' : 'fail :(';
|
||||||
|
},
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException UnexpectedValueException
|
||||||
|
* @dataProvider getBrokenPipes
|
||||||
|
*/
|
||||||
|
public function testThrowsExceptionForBrokenPipes($tpl, $data)
|
||||||
|
{
|
||||||
|
$this->mustache
|
||||||
|
->loadTemplate(sprintf('{{%% FILTERS }}{{ %s }}', $tpl))
|
||||||
|
->render($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBrokenPipes()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('foo | bar', array()),
|
||||||
|
array('foo | bar', array('foo' => 'FOO')),
|
||||||
|
array('foo | bar', array('foo' => 'FOO', 'bar' => 'BAR')),
|
||||||
|
array('foo | bar', array('foo' => 'FOO', 'bar' => array(1, 2))),
|
||||||
|
array('foo | bar | baz', array('foo' => 'FOO', 'bar' => function() { return 'BAR'; })),
|
||||||
|
array('foo | bar | baz', array('foo' => 'FOO', 'baz' => function() { return 'BAZ'; })),
|
||||||
|
array('foo | bar | baz', array('bar' => function() { return 'BAR'; })),
|
||||||
|
array('foo | bar | baz', array('baz' => function() { return 'BAZ'; })),
|
||||||
|
array('foo | bar.baz', array('foo' => 'FOO', 'bar' => function() { return 'BAR'; }, 'baz' => function() { return 'BAZ'; })),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,15 +13,17 @@
|
|||||||
* @group lambdas
|
* @group lambdas
|
||||||
* @group functional
|
* @group functional
|
||||||
*/
|
*/
|
||||||
class Mustache_Test_FiveThree_Functional_HigherOrderSectionsTest extends PHPUnit_Framework_TestCase {
|
class Mustache_Test_FiveThree_Functional_HigherOrderSectionsTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
private $mustache;
|
private $mustache;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp()
|
||||||
|
{
|
||||||
$this->mustache = new Mustache_Engine;
|
$this->mustache = new Mustache_Engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAnonymousFunctionSectionCallback() {
|
public function testAnonymousFunctionSectionCallback()
|
||||||
|
{
|
||||||
$tpl = $this->mustache->loadTemplate('{{#wrapper}}{{name}}{{/wrapper}}');
|
$tpl = $this->mustache->loadTemplate('{{#wrapper}}{{name}}{{/wrapper}}');
|
||||||
|
|
||||||
$foo = new Mustache_Test_FiveThree_Functional_Foo;
|
$foo = new Mustache_Test_FiveThree_Functional_Foo;
|
||||||
@@ -33,7 +35,8 @@ class Mustache_Test_FiveThree_Functional_HigherOrderSectionsTest extends PHPUnit
|
|||||||
$this->assertEquals(sprintf('<div class="anonymous">%s</div>', $foo->name), $tpl->render($foo));
|
$this->assertEquals(sprintf('<div class="anonymous">%s</div>', $foo->name), $tpl->render($foo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSectionCallback() {
|
public function testSectionCallback()
|
||||||
|
{
|
||||||
$one = $this->mustache->loadTemplate('{{name}}');
|
$one = $this->mustache->loadTemplate('{{name}}');
|
||||||
$two = $this->mustache->loadTemplate('{{#wrap}}{{name}}{{/wrap}}');
|
$two = $this->mustache->loadTemplate('{{#wrap}}{{name}}{{/wrap}}');
|
||||||
|
|
||||||
@@ -44,7 +47,8 @@ class Mustache_Test_FiveThree_Functional_HigherOrderSectionsTest extends PHPUnit
|
|||||||
$this->assertEquals(sprintf('<em>%s</em>', $foo->name), $two->render($foo));
|
$this->assertEquals(sprintf('<em>%s</em>', $foo->name), $two->render($foo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testViewArrayAnonymousSectionCallback() {
|
public function testViewArrayAnonymousSectionCallback()
|
||||||
|
{
|
||||||
$tpl = $this->mustache->loadTemplate('{{#wrap}}{{name}}{{/wrap}}');
|
$tpl = $this->mustache->loadTemplate('{{#wrap}}{{name}}{{/wrap}}');
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
@@ -58,12 +62,14 @@ class Mustache_Test_FiveThree_Functional_HigherOrderSectionsTest extends PHPUnit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Mustache_Test_FiveThree_Functional_Foo {
|
class Mustache_Test_FiveThree_Functional_Foo
|
||||||
|
{
|
||||||
public $name = 'Justin';
|
public $name = 'Justin';
|
||||||
public $lorem = 'Lorem ipsum dolor sit amet,';
|
public $lorem = 'Lorem ipsum dolor sit amet,';
|
||||||
public $wrap;
|
public $wrap;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct()
|
||||||
|
{
|
||||||
$this->wrap = function($text) {
|
$this->wrap = function($text) {
|
||||||
return sprintf('<em>%s</em>', $text);
|
return sprintf('<em>%s</em>', $text);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group lambdas
|
||||||
|
* @group functional
|
||||||
|
*/
|
||||||
|
class Mustache_Test_FiveThree_Functional_LambdaHelperTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
private $mustache;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->mustache = new Mustache_Engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSectionLambdaHelper()
|
||||||
|
{
|
||||||
|
$one = $this->mustache->loadTemplate('{{name}}');
|
||||||
|
$two = $this->mustache->loadTemplate('{{#lambda}}{{name}}{{/lambda}}');
|
||||||
|
|
||||||
|
$foo = new StdClass;
|
||||||
|
$foo->name = 'Mario';
|
||||||
|
$foo->lambda = function($text, $mustache) {
|
||||||
|
return strtoupper($mustache->render($text));
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->assertEquals('Mario', $one->render($foo));
|
||||||
|
$this->assertEquals('MARIO', $two->render($foo));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,11 +15,12 @@
|
|||||||
* @group mustache-spec
|
* @group mustache-spec
|
||||||
* @group functional
|
* @group functional
|
||||||
*/
|
*/
|
||||||
class Mustache_Test_FiveThree_Functional_MustacheSpecTest extends PHPUnit_Framework_TestCase {
|
class Mustache_Test_FiveThree_Functional_MustacheSpecTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
private static $mustache;
|
private static $mustache;
|
||||||
|
|
||||||
public static function setUpBeforeClass() {
|
public static function setUpBeforeClass()
|
||||||
|
{
|
||||||
self::$mustache = new Mustache_Engine;
|
self::$mustache = new Mustache_Engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +28,8 @@ class Mustache_Test_FiveThree_Functional_MustacheSpecTest extends PHPUnit_Framew
|
|||||||
* For some reason data providers can't mark tests skipped, so this test exists
|
* 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.
|
* simply to provide a 'skipped' test if the `spec` submodule isn't initialized.
|
||||||
*/
|
*/
|
||||||
public function testSpecInitialized() {
|
public function testSpecInitialized()
|
||||||
|
{
|
||||||
if (!file_exists(dirname(__FILE__).'/../../../../../vendor/spec/specs/')) {
|
if (!file_exists(dirname(__FILE__).'/../../../../../vendor/spec/specs/')) {
|
||||||
$this->markTestSkipped('Mustache spec submodule not initialized: run "git submodule update --init"');
|
$this->markTestSkipped('Mustache spec submodule not initialized: run "git submodule update --init"');
|
||||||
}
|
}
|
||||||
@@ -37,19 +39,22 @@ class Mustache_Test_FiveThree_Functional_MustacheSpecTest extends PHPUnit_Framew
|
|||||||
* @group lambdas
|
* @group lambdas
|
||||||
* @dataProvider loadLambdasSpec
|
* @dataProvider loadLambdasSpec
|
||||||
*/
|
*/
|
||||||
public function testLambdasSpec($desc, $source, $partials, $data, $expected) {
|
public function testLambdasSpec($desc, $source, $partials, $data, $expected)
|
||||||
|
{
|
||||||
$template = self::loadTemplate($source, $partials);
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->assertEquals($expected, $template($this->prepareLambdasSpec($data)), $desc);
|
$this->assertEquals($expected, $template($this->prepareLambdasSpec($data)), $desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadLambdasSpec() {
|
public function loadLambdasSpec()
|
||||||
|
{
|
||||||
return $this->loadSpec('~lambdas');
|
return $this->loadSpec('~lambdas');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract and lambdafy any 'lambda' values found in the $data array.
|
* Extract and lambdafy any 'lambda' values found in the $data array.
|
||||||
*/
|
*/
|
||||||
private function prepareLambdasSpec($data) {
|
private function prepareLambdasSpec($data)
|
||||||
|
{
|
||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
if ($key === 'lambda') {
|
if ($key === 'lambda') {
|
||||||
if (!isset($val['php'])) {
|
if (!isset($val['php'])) {
|
||||||
@@ -60,7 +65,7 @@ class Mustache_Test_FiveThree_Functional_MustacheSpecTest extends PHPUnit_Framew
|
|||||||
$data[$key] = function($text = null) use ($func) {
|
$data[$key] = function($text = null) use ($func) {
|
||||||
return eval($func);
|
return eval($func);
|
||||||
};
|
};
|
||||||
} else if (is_array($val)) {
|
} elseif (is_array($val)) {
|
||||||
$data[$key] = $this->prepareLambdasSpec($val);
|
$data[$key] = $this->prepareLambdasSpec($val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +81,8 @@ class Mustache_Test_FiveThree_Functional_MustacheSpecTest extends PHPUnit_Framew
|
|||||||
* @access public
|
* @access public
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function loadSpec($name) {
|
private function loadSpec($name)
|
||||||
|
{
|
||||||
$filename = dirname(__FILE__) . '/../../../../../vendor/spec/specs/' . $name . '.yml';
|
$filename = dirname(__FILE__) . '/../../../../../vendor/spec/specs/' . $name . '.yml';
|
||||||
if (!file_exists($filename)) {
|
if (!file_exists($filename)) {
|
||||||
return array();
|
return array();
|
||||||
@@ -106,7 +112,8 @@ class Mustache_Test_FiveThree_Functional_MustacheSpecTest extends PHPUnit_Framew
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function loadTemplate($source, $partials) {
|
private static function loadTemplate($source, $partials)
|
||||||
|
{
|
||||||
self::$mustache->setPartials($partials);
|
self::$mustache->setPartials($partials);
|
||||||
|
|
||||||
return self::$mustache->loadTemplate($source);
|
return self::$mustache->loadTemplate($source);
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ class Mustache_Test_Functional_MustacheInjectionTest extends PHPUnit_Framework_T
|
|||||||
$this->assertEquals('{{ b }}', $tpl->render($data));
|
$this->assertEquals('{{ b }}', $tpl->render($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// sections
|
// sections
|
||||||
|
|
||||||
public function testSectionInjection()
|
public function testSectionInjection()
|
||||||
@@ -78,7 +77,6 @@ class Mustache_Test_Functional_MustacheInjectionTest extends PHPUnit_Framework_T
|
|||||||
$this->assertEquals('{{ c }}', $tpl->render($data));
|
$this->assertEquals('{{ c }}', $tpl->render($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// partials
|
// partials
|
||||||
|
|
||||||
public function testPartialInjection()
|
public function testPartialInjection()
|
||||||
@@ -111,7 +109,6 @@ class Mustache_Test_Functional_MustacheInjectionTest extends PHPUnit_Framework_T
|
|||||||
$this->assertEquals('{{ b }}', $tpl->render($data));
|
$this->assertEquals('{{ b }}', $tpl->render($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// lambdas
|
// lambdas
|
||||||
|
|
||||||
public function testLambdaInterpolationInjection()
|
public function testLambdaInterpolationInjection()
|
||||||
|
|||||||
@@ -30,6 +30,19 @@ class Mustache_Test_Loader_FilesystemLoaderTest extends PHPUnit_Framework_TestCa
|
|||||||
$this->assertEquals('two contents', $loader->load('two.mustache'));
|
$this->assertEquals('two contents', $loader->load('two.mustache'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEmptyExtensionString()
|
||||||
|
{
|
||||||
|
$baseDir = realpath(dirname(__FILE__).'/../../../fixtures/templates');
|
||||||
|
|
||||||
|
$loader = new Mustache_Loader_FilesystemLoader($baseDir, array('extension' => ''));
|
||||||
|
$this->assertEquals('one contents', $loader->load('one.mustache'));
|
||||||
|
$this->assertEquals('alpha contents', $loader->load('alpha.ms'));
|
||||||
|
|
||||||
|
$loader = new Mustache_Loader_FilesystemLoader($baseDir, array('extension' => null));
|
||||||
|
$this->assertEquals('two contents', $loader->load('two.mustache'));
|
||||||
|
$this->assertEquals('beta contents', $loader->load('beta.ms'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException RuntimeException
|
* @expectedException RuntimeException
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class Mustache_Test_Logger_AbstractLoggerTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testEverything()
|
||||||
|
{
|
||||||
|
$logger = new Mustache_Test_Logger_TestLogger;
|
||||||
|
|
||||||
|
$logger->emergency('emergency message');
|
||||||
|
$logger->alert('alert message');
|
||||||
|
$logger->critical('critical message');
|
||||||
|
$logger->error('error message');
|
||||||
|
$logger->warning('warning message');
|
||||||
|
$logger->notice('notice message');
|
||||||
|
$logger->info('info message');
|
||||||
|
$logger->debug('debug message');
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
array(Mustache_Logger::EMERGENCY, 'emergency message', array()),
|
||||||
|
array(Mustache_Logger::ALERT, 'alert message', array()),
|
||||||
|
array(Mustache_Logger::CRITICAL, 'critical message', array()),
|
||||||
|
array(Mustache_Logger::ERROR, 'error message', array()),
|
||||||
|
array(Mustache_Logger::WARNING, 'warning message', array()),
|
||||||
|
array(Mustache_Logger::NOTICE, 'notice message', array()),
|
||||||
|
array(Mustache_Logger::INFO, 'info message', array()),
|
||||||
|
array(Mustache_Logger::DEBUG, 'debug message', array()),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $logger->log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mustache_Test_Logger_TestLogger extends Mustache_Logger_AbstractLogger
|
||||||
|
{
|
||||||
|
public $log = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs with an arbitrary level.
|
||||||
|
*
|
||||||
|
* @param mixed $level
|
||||||
|
* @param string $message
|
||||||
|
* @param array $context
|
||||||
|
*/
|
||||||
|
public function log($level, $message, array $context = array())
|
||||||
|
{
|
||||||
|
$this->log[] = array($level, $message, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Mustache.php.
|
||||||
|
*
|
||||||
|
* (c) 2012 Justin Hileman
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class Mustache_Test_Logger_StreamLoggerTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testAcceptsFilename()
|
||||||
|
{
|
||||||
|
$name = tempnam(sys_get_temp_dir(), 'mustache-test');
|
||||||
|
$logger = new Mustache_Logger_StreamLogger($name);
|
||||||
|
$logger->log(Mustache_Logger::CRITICAL, 'message');
|
||||||
|
|
||||||
|
$this->assertEquals("CRITICAL: message\n", file_get_contents($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAcceptsResource()
|
||||||
|
{
|
||||||
|
$name = tempnam(sys_get_temp_dir(), 'mustache-test');
|
||||||
|
$file = fopen($name, 'a');
|
||||||
|
$logger = new Mustache_Logger_StreamLogger($file);
|
||||||
|
$logger->log(Mustache_Logger::CRITICAL, 'message');
|
||||||
|
|
||||||
|
$this->assertEquals("CRITICAL: message\n", file_get_contents($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException LogicException
|
||||||
|
*/
|
||||||
|
public function testPrematurelyClosedStreamThrowsException()
|
||||||
|
{
|
||||||
|
$stream = tmpfile();
|
||||||
|
$logger = new Mustache_Logger_StreamLogger($stream);
|
||||||
|
fclose($stream);
|
||||||
|
|
||||||
|
$logger->log(Mustache_Logger::CRITICAL, 'message');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getLevels
|
||||||
|
*/
|
||||||
|
public function testLoggingThresholds($logLevel, $level, $shouldLog)
|
||||||
|
{
|
||||||
|
$stream = tmpfile();
|
||||||
|
$logger = new Mustache_Logger_StreamLogger($stream, $logLevel);
|
||||||
|
$logger->log($level, "logged");
|
||||||
|
|
||||||
|
rewind($stream);
|
||||||
|
$result = fread($stream, 1024);
|
||||||
|
|
||||||
|
if ($shouldLog) {
|
||||||
|
$this->assertContains("logged", $result);
|
||||||
|
} else {
|
||||||
|
$this->assertEmpty($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLevels()
|
||||||
|
{
|
||||||
|
// $logLevel, $level, $shouldLog
|
||||||
|
return array(
|
||||||
|
// identities
|
||||||
|
array(Mustache_Logger::EMERGENCY, Mustache_Logger::EMERGENCY, true),
|
||||||
|
array(Mustache_Logger::ALERT, Mustache_Logger::ALERT, true),
|
||||||
|
array(Mustache_Logger::CRITICAL, Mustache_Logger::CRITICAL, true),
|
||||||
|
array(Mustache_Logger::ERROR, Mustache_Logger::ERROR, true),
|
||||||
|
array(Mustache_Logger::WARNING, Mustache_Logger::WARNING, true),
|
||||||
|
array(Mustache_Logger::NOTICE, Mustache_Logger::NOTICE, true),
|
||||||
|
array(Mustache_Logger::INFO, Mustache_Logger::INFO, true),
|
||||||
|
array(Mustache_Logger::DEBUG, Mustache_Logger::DEBUG, true),
|
||||||
|
|
||||||
|
// one above
|
||||||
|
array(Mustache_Logger::ALERT, Mustache_Logger::EMERGENCY, true),
|
||||||
|
array(Mustache_Logger::CRITICAL, Mustache_Logger::ALERT, true),
|
||||||
|
array(Mustache_Logger::ERROR, Mustache_Logger::CRITICAL, true),
|
||||||
|
array(Mustache_Logger::WARNING, Mustache_Logger::ERROR, true),
|
||||||
|
array(Mustache_Logger::NOTICE, Mustache_Logger::WARNING, true),
|
||||||
|
array(Mustache_Logger::INFO, Mustache_Logger::NOTICE, true),
|
||||||
|
array(Mustache_Logger::DEBUG, Mustache_Logger::INFO, true),
|
||||||
|
|
||||||
|
// one below
|
||||||
|
array(Mustache_Logger::EMERGENCY, Mustache_Logger::ALERT, false),
|
||||||
|
array(Mustache_Logger::ALERT, Mustache_Logger::CRITICAL, false),
|
||||||
|
array(Mustache_Logger::CRITICAL, Mustache_Logger::ERROR, false),
|
||||||
|
array(Mustache_Logger::ERROR, Mustache_Logger::WARNING, false),
|
||||||
|
array(Mustache_Logger::WARNING, Mustache_Logger::NOTICE, false),
|
||||||
|
array(Mustache_Logger::NOTICE, Mustache_Logger::INFO, false),
|
||||||
|
array(Mustache_Logger::INFO, Mustache_Logger::DEBUG, false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getLogMessages
|
||||||
|
*/
|
||||||
|
public function testLogging($level, $message, $context, $expected)
|
||||||
|
{
|
||||||
|
$stream = tmpfile();
|
||||||
|
$logger = new Mustache_Logger_StreamLogger($stream, Mustache_Logger::DEBUG);
|
||||||
|
$logger->log($level, $message, $context);
|
||||||
|
|
||||||
|
rewind($stream);
|
||||||
|
$result = fread($stream, 1024);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogMessages()
|
||||||
|
{
|
||||||
|
// $level, $message, $context, $expected
|
||||||
|
return array(
|
||||||
|
array(Mustache_Logger::DEBUG, 'debug message', array(), "DEBUG: debug message\n"),
|
||||||
|
array(Mustache_Logger::INFO, 'info message', array(), "INFO: info message\n"),
|
||||||
|
array(Mustache_Logger::NOTICE, 'notice message', array(), "NOTICE: notice message\n"),
|
||||||
|
array(Mustache_Logger::WARNING, 'warning message', array(), "WARNING: warning message\n"),
|
||||||
|
array(Mustache_Logger::ERROR, 'error message', array(), "ERROR: error message\n"),
|
||||||
|
array(Mustache_Logger::CRITICAL, 'critical message', array(), "CRITICAL: critical message\n"),
|
||||||
|
array(Mustache_Logger::ALERT, 'alert message', array(), "ALERT: alert message\n"),
|
||||||
|
array(Mustache_Logger::EMERGENCY, 'emergency message', array(), "EMERGENCY: emergency message\n"),
|
||||||
|
|
||||||
|
// with context
|
||||||
|
array(
|
||||||
|
Mustache_Logger::ERROR,
|
||||||
|
'error message',
|
||||||
|
array('name' => 'foo', 'number' => 42),
|
||||||
|
"ERROR: error message\n"
|
||||||
|
),
|
||||||
|
|
||||||
|
// with interpolation
|
||||||
|
array(
|
||||||
|
Mustache_Logger::ERROR,
|
||||||
|
'error {name}-{number}',
|
||||||
|
array('name' => 'foo', 'number' => 42),
|
||||||
|
"ERROR: error foo-42\n"
|
||||||
|
),
|
||||||
|
|
||||||
|
// with iterpolation false positive
|
||||||
|
array(
|
||||||
|
Mustache_Logger::ERROR,
|
||||||
|
'error {nothing}',
|
||||||
|
array('name' => 'foo', 'number' => 42),
|
||||||
|
"ERROR: error {nothing}\n"
|
||||||
|
),
|
||||||
|
|
||||||
|
// with interpolation injection
|
||||||
|
array(
|
||||||
|
Mustache_Logger::ERROR,
|
||||||
|
'{foo}',
|
||||||
|
array('foo' => '{bar}', 'bar' => 'FAIL'),
|
||||||
|
"ERROR: {bar}\n"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChangeLoggingLevels()
|
||||||
|
{
|
||||||
|
$stream = tmpfile();
|
||||||
|
$logger = new Mustache_Logger_StreamLogger($stream);
|
||||||
|
|
||||||
|
$logger->setLevel(Mustache_Logger::ERROR);
|
||||||
|
$this->assertEquals(Mustache_Logger::ERROR, $logger->getLevel());
|
||||||
|
|
||||||
|
$logger->log(Mustache_Logger::WARNING, 'ignore this');
|
||||||
|
|
||||||
|
$logger->setLevel(Mustache_Logger::INFO);
|
||||||
|
$this->assertEquals(Mustache_Logger::INFO, $logger->getLevel());
|
||||||
|
|
||||||
|
$logger->log(Mustache_Logger::WARNING, 'log this');
|
||||||
|
|
||||||
|
$logger->setLevel(Mustache_Logger::CRITICAL);
|
||||||
|
$this->assertEquals(Mustache_Logger::CRITICAL, $logger->getLevel());
|
||||||
|
|
||||||
|
$logger->log(Mustache_Logger::ERROR, 'ignore this');
|
||||||
|
|
||||||
|
rewind($stream);
|
||||||
|
$result = fread($stream, 1024);
|
||||||
|
|
||||||
|
$this->assertEquals("WARNING: log this\n", $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testThrowsInvalidArgumentExceptionWhenSettingUnknownLevels()
|
||||||
|
{
|
||||||
|
$logger = new Mustache_Logger_StreamLogger(tmpfile());
|
||||||
|
$logger->setLevel('bacon');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testThrowsInvalidArgumentExceptionWhenLoggingUnknownLevels()
|
||||||
|
{
|
||||||
|
$logger = new Mustache_Logger_StreamLogger(tmpfile());
|
||||||
|
$logger->log('bacon', 'CODE BACON ERROR!');
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class Partials {
|
class Partials
|
||||||
|
{
|
||||||
public $page = array(
|
public $page = array(
|
||||||
'title' => 'Page Title',
|
'title' => 'Page Title',
|
||||||
'subtitle' => 'Page Subtitle',
|
'subtitle' => 'Page Subtitle',
|
||||||
|
|||||||
Reference in New Issue
Block a user