|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is part of Mustache.php.
|
|
|
|
*
|
|
|
|
* (c) 2010-2017 Justin Hileman
|
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A Mustache implementation in PHP.
|
|
|
|
*
|
|
|
|
* {@link http://defunkt.github.com/mustache}
|
|
|
|
*
|
|
|
|
* Mustache is a framework-agnostic logic-less templating language. It enforces separation of view
|
|
|
|
* logic from template files. In fact, it is not even possible to embed logic in the template.
|
|
|
|
*
|
|
|
|
* This is very, very rad.
|
|
|
|
*
|
|
|
|
* @author Justin Hileman {@link http://justinhileman.com}
|
|
|
|
*/
|
|
|
|
class Mustache_Engine
|
|
|
|
{
|
PHP SESSION Prefix and IP check, engine constants and user_constants as a function for better memory usage, add SQLite 3 driver, new loader for aditional database method, new REST HTPP method check, updated template engines: Mustache 2.13, Smarty 3.1.34, Twig 1.42.5, Twig 2.12.5, add Twig 3 support to PHP 7.2+, define Dwoo template as deprecated, Caches and captcha bugfix in PHP 5.4.x
5 years ago
|
|
|
const VERSION = '2.13.0';
|
|
|
|
const SPEC_VERSION = '1.1.2';
|
|
|
|
|
|
|
|
const PRAGMA_FILTERS = 'FILTERS';
|
|
|
|
const PRAGMA_BLOCKS = 'BLOCKS';
|
|
|
|
const PRAGMA_ANCHORED_DOT = 'ANCHORED-DOT';
|
|
|
|
|
|
|
|
// Known pragmas
|
|
|
|
private static $knownPragmas = array(
|
|
|
|
self::PRAGMA_FILTERS => true,
|
|
|
|
self::PRAGMA_BLOCKS => true,
|
|
|
|
self::PRAGMA_ANCHORED_DOT => true,
|
|
|
|
);
|
|
|
|
|
|
|
|
// Template cache
|
|
|
|
private $templates = array();
|
|
|
|
|
|
|
|
// Environment
|
|
|
|
private $templateClassPrefix = '__Mustache_';
|
|
|
|
private $cache;
|
|
|
|
private $lambdaCache;
|
|
|
|
private $cacheLambdaTemplates = false;
|
|
|
|
private $loader;
|
|
|
|
private $partialsLoader;
|
|
|
|
private $helpers;
|
|
|
|
private $escape;
|
|
|
|
private $entityFlags = ENT_COMPAT;
|
|
|
|
private $charset = 'UTF-8';
|
|
|
|
private $logger;
|
|
|
|
private $strictCallables = false;
|
|
|
|
private $pragmas = array();
|
|
|
|
private $delimiters;
|
|
|
|
|
|
|
|
// Services
|
|
|
|
private $tokenizer;
|
|
|
|
private $parser;
|
|
|
|
private $compiler;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mustache class constructor.
|
|
|
|
*
|
|
|
|
* Passing an $options array allows overriding certain Mustache options during instantiation:
|
|
|
|
*
|
|
|
|
* $options = array(
|
|
|
|
* // The class prefix for compiled templates. Defaults to '__Mustache_'.
|
|
|
|
* 'template_class_prefix' => '__MyTemplates_',
|
|
|
|
*
|
|
|
|
* // A Mustache cache instance or a cache directory string for compiled templates.
|
|
|
|
* // Mustache will not cache templates unless this is set.
|
|
|
|
* 'cache' => dirname(__FILE__).'/tmp/cache/mustache',
|
|
|
|
*
|
|
|
|
* // 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,
|
|
|
|
*
|
|
|
|
* // Optionally, enable caching for lambda section templates. This is generally not recommended, as lambda
|
|
|
|
* // sections are often too dynamic to benefit from caching.
|
|
|
|
* 'cache_lambda_templates' => true,
|
|
|
|
*
|
|
|
|
* // Customize the tag delimiters used by this engine instance. Note that overriding here changes the
|
|
|
|
* // delimiters used to parse all templates and partials loaded by this instance. To override just for a
|
|
|
|
* // single template, use an inline "change delimiters" tag at the start of the template file:
|
|
|
|
* //
|
|
|
|
* // {{=<% %>=}}
|
|
|
|
* //
|
|
|
|
* 'delimiters' => '<% %>',
|
|
|
|
*
|
|
|
|
* // A Mustache template loader instance. Uses a StringLoader if not specified.
|
|
|
|
* 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
|
|
|
|
*
|
|
|
|
* // A Mustache loader instance for partials.
|
|
|
|
* 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views/partials'),
|
|
|
|
*
|
|
|
|
* // An array of Mustache partials. Useful for quick-and-dirty string template loading, but not as
|
|
|
|
* // efficient or lazy as a Filesystem (or database) loader.
|
|
|
|
* 'partials' => array('foo' => file_get_contents(dirname(__FILE__).'/views/partials/foo.mustache')),
|
|
|
|
*
|
|
|
|
* // An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order
|
|
|
|
* // sections), or any other valid Mustache context value. They will be prepended to the context stack,
|
|
|
|
* // so they will be available in any template loaded by this Mustache instance.
|
|
|
|
* 'helpers' => array('i18n' => function ($text) {
|
|
|
|
* // do something translatey here...
|
|
|
|
* }),
|
|
|
|
*
|
|
|
|
* // An 'escape' callback, responsible for escaping double-mustache variables.
|
|
|
|
* 'escape' => function ($value) {
|
|
|
|
* return htmlspecialchars($buffer, ENT_COMPAT, 'UTF-8');
|
|
|
|
* },
|
|
|
|
*
|
|
|
|
* // Type argument for `htmlspecialchars`. Defaults to ENT_COMPAT. You may prefer ENT_QUOTES.
|
|
|
|
* 'entity_flags' => ENT_QUOTES,
|
|
|
|
*
|
|
|
|
* // Character set for `htmlspecialchars`. Defaults to 'UTF-8'. Use 'UTF-8'.
|
|
|
|
* '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_Logger_StreamLogger('php://stderr'),
|
|
|
|
*
|
|
|
|
* // Only treat Closure instances and invokable classes as callable. If true, values like
|
|
|
|
* // `array('ClassName', 'methodName')` and `array($classInstance, 'methodName')`, which are traditionally
|
|
|
|
* // "callable" in PHP, are not called to resolve variables for interpolation or section contexts. This
|
|
|
|
* // helps protect against arbitrary code execution when user input is passed directly into the template.
|
|
|
|
* // This currently defaults to false, but will default to true in v3.0.
|
|
|
|
* 'strict_callables' => true,
|
|
|
|
*
|
|
|
|
* // Enable pragmas across all templates, regardless of the presence of pragma tags in the individual
|
|
|
|
* // templates.
|
|
|
|
* 'pragmas' => [Mustache_Engine::PRAGMA_FILTERS],
|
|
|
|
* );
|
|
|
|
*
|
|
|
|
* @throws Mustache_Exception_InvalidArgumentException If `escape` option is not callable
|
|
|
|
*
|
|
|
|
* @param array $options (default: array())
|
|
|
|
*/
|
|
|
|
public function __construct(array $options = array())
|
|
|
|
{
|
|
|
|
if (isset($options['template_class_prefix'])) {
|
|
|
|
if ((string) $options['template_class_prefix'] === '') {
|
|
|
|
throw new Mustache_Exception_InvalidArgumentException('Mustache Constructor "template_class_prefix" must not be empty');
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->templateClassPrefix = $options['template_class_prefix'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['cache'])) {
|
|
|
|
$cache = $options['cache'];
|
|
|
|
|
|
|
|
if (is_string($cache)) {
|
|
|
|
$mode = isset($options['cache_file_mode']) ? $options['cache_file_mode'] : null;
|
|
|
|
$cache = new Mustache_Cache_FilesystemCache($cache, $mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->setCache($cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['cache_lambda_templates'])) {
|
|
|
|
$this->cacheLambdaTemplates = (bool) $options['cache_lambda_templates'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['loader'])) {
|
|
|
|
$this->setLoader($options['loader']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['partials_loader'])) {
|
|
|
|
$this->setPartialsLoader($options['partials_loader']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['partials'])) {
|
|
|
|
$this->setPartials($options['partials']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['helpers'])) {
|
|
|
|
$this->setHelpers($options['helpers']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['escape'])) {
|
|
|
|
if (!is_callable($options['escape'])) {
|
|
|
|
throw new Mustache_Exception_InvalidArgumentException('Mustache Constructor "escape" option must be callable');
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->escape = $options['escape'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['entity_flags'])) {
|
|
|
|
$this->entityFlags = $options['entity_flags'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['charset'])) {
|
|
|
|
$this->charset = $options['charset'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['logger'])) {
|
|
|
|
$this->setLogger($options['logger']);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['strict_callables'])) {
|
|
|
|
$this->strictCallables = $options['strict_callables'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['delimiters'])) {
|
|
|
|
$this->delimiters = $options['delimiters'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['pragmas'])) {
|
|
|
|
foreach ($options['pragmas'] as $pragma) {
|
|
|
|
if (!isset(self::$knownPragmas[$pragma])) {
|
|
|
|
throw new Mustache_Exception_InvalidArgumentException(sprintf('Unknown pragma: "%s".', $pragma));
|
|
|
|
}
|
|
|
|
$this->pragmas[$pragma] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shortcut 'render' invocation.
|
|
|
|
*
|
|
|
|
* Equivalent to calling `$mustache->loadTemplate($template)->render($context);`
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::loadTemplate
|
|
|
|
* @see Mustache_Template::render
|
|
|
|
*
|
|
|
|
* @param string $template
|
|
|
|
* @param mixed $context (default: array())
|
|
|
|
*
|
|
|
|
* @return string Rendered template
|
|
|
|
*/
|
|
|
|
public function render($template, $context = array())
|
|
|
|
{
|
|
|
|
return $this->loadTemplate($template)->render($context);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache escape callback.
|
|
|
|
*
|
|
|
|
* @return callable|null
|
|
|
|
*/
|
|
|
|
public function getEscape()
|
|
|
|
{
|
|
|
|
return $this->escape;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache entitity type to escape.
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function getEntityFlags()
|
|
|
|
{
|
|
|
|
return $this->entityFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache character set.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getCharset()
|
|
|
|
{
|
|
|
|
return $this->charset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current globally enabled pragmas.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getPragmas()
|
|
|
|
{
|
|
|
|
return array_keys($this->pragmas);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the Mustache template Loader instance.
|
|
|
|
*
|
|
|
|
* @param Mustache_Loader $loader
|
|
|
|
*/
|
|
|
|
public function setLoader(Mustache_Loader $loader)
|
|
|
|
{
|
|
|
|
$this->loader = $loader;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache template Loader instance.
|
|
|
|
*
|
|
|
|
* If no Loader instance has been explicitly specified, this method will instantiate and return
|
|
|
|
* a StringLoader instance.
|
|
|
|
*
|
|
|
|
* @return Mustache_Loader
|
|
|
|
*/
|
|
|
|
public function getLoader()
|
|
|
|
{
|
|
|
|
if (!isset($this->loader)) {
|
|
|
|
$this->loader = new Mustache_Loader_StringLoader();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->loader;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the Mustache partials Loader instance.
|
|
|
|
*
|
|
|
|
* @param Mustache_Loader $partialsLoader
|
|
|
|
*/
|
|
|
|
public function setPartialsLoader(Mustache_Loader $partialsLoader)
|
|
|
|
{
|
|
|
|
$this->partialsLoader = $partialsLoader;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache partials Loader instance.
|
|
|
|
*
|
|
|
|
* If no Loader instance has been explicitly specified, this method will instantiate and return
|
|
|
|
* an ArrayLoader instance.
|
|
|
|
*
|
|
|
|
* @return Mustache_Loader
|
|
|
|
*/
|
|
|
|
public function getPartialsLoader()
|
|
|
|
{
|
|
|
|
if (!isset($this->partialsLoader)) {
|
|
|
|
$this->partialsLoader = new Mustache_Loader_ArrayLoader();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->partialsLoader;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set partials for the current partials Loader instance.
|
|
|
|
*
|
|
|
|
* @throws Mustache_Exception_RuntimeException If the current Loader instance is immutable
|
|
|
|
*
|
|
|
|
* @param array $partials (default: array())
|
|
|
|
*/
|
|
|
|
public function setPartials(array $partials = array())
|
|
|
|
{
|
|
|
|
if (!isset($this->partialsLoader)) {
|
|
|
|
$this->partialsLoader = new Mustache_Loader_ArrayLoader();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$this->partialsLoader instanceof Mustache_Loader_MutableLoader) {
|
|
|
|
throw new Mustache_Exception_RuntimeException('Unable to set partials on an immutable Mustache Loader instance');
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->partialsLoader->setTemplates($partials);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set an array of Mustache helpers.
|
|
|
|
*
|
|
|
|
* An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order sections), or
|
|
|
|
* any other valid Mustache context value. They will be prepended to the context stack, so they will be available in
|
|
|
|
* any template loaded by this Mustache instance.
|
|
|
|
*
|
|
|
|
* @throws Mustache_Exception_InvalidArgumentException if $helpers is not an array or Traversable
|
|
|
|
*
|
|
|
|
* @param array|Traversable $helpers
|
|
|
|
*/
|
|
|
|
public function setHelpers($helpers)
|
|
|
|
{
|
|
|
|
if (!is_array($helpers) && !$helpers instanceof Traversable) {
|
|
|
|
throw new Mustache_Exception_InvalidArgumentException('setHelpers expects an array of helpers');
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->getHelpers()->clear();
|
|
|
|
|
|
|
|
foreach ($helpers as $name => $helper) {
|
|
|
|
$this->addHelper($name, $helper);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current set of Mustache helpers.
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::setHelpers
|
|
|
|
*
|
|
|
|
* @return Mustache_HelperCollection
|
|
|
|
*/
|
|
|
|
public function getHelpers()
|
|
|
|
{
|
|
|
|
if (!isset($this->helpers)) {
|
|
|
|
$this->helpers = new Mustache_HelperCollection();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->helpers;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a new Mustache helper.
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::setHelpers
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @param mixed $helper
|
|
|
|
*/
|
|
|
|
public function addHelper($name, $helper)
|
|
|
|
{
|
|
|
|
$this->getHelpers()->add($name, $helper);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a Mustache helper by name.
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::setHelpers
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
*
|
|
|
|
* @return mixed Helper
|
|
|
|
*/
|
|
|
|
public function getHelper($name)
|
|
|
|
{
|
|
|
|
return $this->getHelpers()->get($name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check whether this Mustache instance has a helper.
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::setHelpers
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
*
|
|
|
|
* @return bool True if the helper is present
|
|
|
|
*/
|
|
|
|
public function hasHelper($name)
|
|
|
|
{
|
|
|
|
return $this->getHelpers()->has($name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove a helper by name.
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::setHelpers
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
*/
|
|
|
|
public function removeHelper($name)
|
|
|
|
{
|
|
|
|
$this->getHelpers()->remove($name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the Mustache Logger instance.
|
|
|
|
*
|
|
|
|
* @throws Mustache_Exception_InvalidArgumentException If logger is not an instance of Mustache_Logger or Psr\Log\LoggerInterface
|
|
|
|
*
|
|
|
|
* @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 Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->getCache()->getLogger() === null) {
|
|
|
|
$this->getCache()->setLogger($logger);
|
|
|
|
}
|
|
|
|
|
|
|
|
$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.
|
|
|
|
*
|
|
|
|
* @param Mustache_Tokenizer $tokenizer
|
|
|
|
*/
|
|
|
|
public function setTokenizer(Mustache_Tokenizer $tokenizer)
|
|
|
|
{
|
|
|
|
$this->tokenizer = $tokenizer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache Tokenizer instance.
|
|
|
|
*
|
|
|
|
* If no Tokenizer instance has been explicitly specified, this method will instantiate and return a new one.
|
|
|
|
*
|
|
|
|
* @return Mustache_Tokenizer
|
|
|
|
*/
|
|
|
|
public function getTokenizer()
|
|
|
|
{
|
|
|
|
if (!isset($this->tokenizer)) {
|
|
|
|
$this->tokenizer = new Mustache_Tokenizer();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->tokenizer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the Mustache Parser instance.
|
|
|
|
*
|
|
|
|
* @param Mustache_Parser $parser
|
|
|
|
*/
|
|
|
|
public function setParser(Mustache_Parser $parser)
|
|
|
|
{
|
|
|
|
$this->parser = $parser;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache Parser instance.
|
|
|
|
*
|
|
|
|
* If no Parser instance has been explicitly specified, this method will instantiate and return a new one.
|
|
|
|
*
|
|
|
|
* @return Mustache_Parser
|
|
|
|
*/
|
|
|
|
public function getParser()
|
|
|
|
{
|
|
|
|
if (!isset($this->parser)) {
|
|
|
|
$this->parser = new Mustache_Parser();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->parser;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the Mustache Compiler instance.
|
|
|
|
*
|
|
|
|
* @param Mustache_Compiler $compiler
|
|
|
|
*/
|
|
|
|
public function setCompiler(Mustache_Compiler $compiler)
|
|
|
|
{
|
|
|
|
$this->compiler = $compiler;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache Compiler instance.
|
|
|
|
*
|
|
|
|
* If no Compiler instance has been explicitly specified, this method will instantiate and return a new one.
|
|
|
|
*
|
|
|
|
* @return Mustache_Compiler
|
|
|
|
*/
|
|
|
|
public function getCompiler()
|
|
|
|
{
|
|
|
|
if (!isset($this->compiler)) {
|
|
|
|
$this->compiler = new Mustache_Compiler();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->compiler;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the Mustache Cache instance.
|
|
|
|
*
|
|
|
|
* @param Mustache_Cache $cache
|
|
|
|
*/
|
|
|
|
public function setCache(Mustache_Cache $cache)
|
|
|
|
{
|
|
|
|
if (isset($this->logger) && $cache->getLogger() === null) {
|
|
|
|
$cache->setLogger($this->getLogger());
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->cache = $cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Mustache Cache instance.
|
|
|
|
*
|
|
|
|
* If no Cache instance has been explicitly specified, this method will instantiate and return a new one.
|
|
|
|
*
|
|
|
|
* @return Mustache_Cache
|
|
|
|
*/
|
|
|
|
public function getCache()
|
|
|
|
{
|
|
|
|
if (!isset($this->cache)) {
|
|
|
|
$this->setCache(new Mustache_Cache_NoopCache());
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current Lambda Cache instance.
|
|
|
|
*
|
|
|
|
* If 'cache_lambda_templates' is enabled, this is the default cache instance. Otherwise, it is a NoopCache.
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::getCache
|
|
|
|
*
|
|
|
|
* @return Mustache_Cache
|
|
|
|
*/
|
|
|
|
protected function getLambdaCache()
|
|
|
|
{
|
|
|
|
if ($this->cacheLambdaTemplates) {
|
|
|
|
return $this->getCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isset($this->lambdaCache)) {
|
|
|
|
$this->lambdaCache = new Mustache_Cache_NoopCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->lambdaCache;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to generate a Mustache template class.
|
|
|
|
*
|
|
|
|
* This method must be updated any time options are added which make it so
|
|
|
|
* the same template could be parsed and compiled multiple different ways.
|
|
|
|
*
|
|
|
|
* @param string|Mustache_Source $source
|
|
|
|
*
|
|
|
|
* @return string Mustache Template class name
|
|
|
|
*/
|
|
|
|
public function getTemplateClassName($source)
|
|
|
|
{
|
|
|
|
// For the most part, adding a new option here should do the trick.
|
|
|
|
//
|
|
|
|
// Pick a value here which is unique for each possible way the template
|
|
|
|
// could be compiled... but not necessarily unique per option value. See
|
|
|
|
// escape below, which only needs to differentiate between 'custom' and
|
|
|
|
// 'default' escapes.
|
|
|
|
//
|
|
|
|
// Keep this list in alphabetical order :)
|
|
|
|
$chunks = array(
|
|
|
|
'charset' => $this->charset,
|
|
|
|
'delimiters' => $this->delimiters ? $this->delimiters : '{{ }}',
|
|
|
|
'entityFlags' => $this->entityFlags,
|
|
|
|
'escape' => isset($this->escape) ? 'custom' : 'default',
|
|
|
|
'key' => ($source instanceof Mustache_Source) ? $source->getKey() : 'source',
|
|
|
|
'pragmas' => $this->getPragmas(),
|
|
|
|
'strictCallables' => $this->strictCallables,
|
|
|
|
'version' => self::VERSION,
|
|
|
|
);
|
|
|
|
|
|
|
|
$key = json_encode($chunks);
|
|
|
|
|
|
|
|
// Template Source instances have already provided their own source key. For strings, just include the whole
|
|
|
|
// source string in the md5 hash.
|
|
|
|
if (!$source instanceof Mustache_Source) {
|
|
|
|
$key .= "\n" . $source;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->templateClassPrefix . md5($key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load a Mustache Template by name.
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
*
|
|
|
|
* @return Mustache_Template
|
|
|
|
*/
|
|
|
|
public function loadTemplate($name)
|
|
|
|
{
|
|
|
|
return $this->loadSource($this->getLoader()->load($name));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load a Mustache partial Template by name.
|
|
|
|
*
|
|
|
|
* This is a helper method used internally by Template instances for loading partial templates. You can most likely
|
|
|
|
* ignore it completely.
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
*
|
|
|
|
* @return Mustache_Template
|
|
|
|
*/
|
|
|
|
public function loadPartial($name)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
if (isset($this->partialsLoader)) {
|
|
|
|
$loader = $this->partialsLoader;
|
|
|
|
} elseif (isset($this->loader) && !$this->loader instanceof Mustache_Loader_StringLoader) {
|
|
|
|
$loader = $this->loader;
|
|
|
|
} else {
|
|
|
|
throw new Mustache_Exception_UnknownTemplateException($name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->loadSource($loader->load($name));
|
|
|
|
} catch (Mustache_Exception_UnknownTemplateException $e) {
|
|
|
|
// If the named partial cannot be found, log then return null.
|
|
|
|
$this->log(
|
|
|
|
Mustache_Logger::WARNING,
|
|
|
|
'Partial not found: "{name}"',
|
|
|
|
array('name' => $e->getTemplateName())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load a Mustache lambda Template by source.
|
|
|
|
*
|
|
|
|
* This is a helper method used by Template instances to generate subtemplates for Lambda sections. You can most
|
|
|
|
* likely ignore it completely.
|
|
|
|
*
|
|
|
|
* @param string $source
|
|
|
|
* @param string $delims (default: null)
|
|
|
|
*
|
|
|
|
* @return Mustache_Template
|
|
|
|
*/
|
|
|
|
public function loadLambda($source, $delims = null)
|
|
|
|
{
|
|
|
|
if ($delims !== null) {
|
|
|
|
$source = $delims . "\n" . $source;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->loadSource($source, $this->getLambdaCache());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instantiate and return a Mustache Template instance by source.
|
|
|
|
*
|
|
|
|
* Optionally provide a Mustache_Cache instance. This is used internally by Mustache_Engine::loadLambda to respect
|
|
|
|
* the 'cache_lambda_templates' configuration option.
|
|
|
|
*
|
|
|
|
* @see Mustache_Engine::loadTemplate
|
|
|
|
* @see Mustache_Engine::loadPartial
|
|
|
|
* @see Mustache_Engine::loadLambda
|
|
|
|
*
|
|
|
|
* @param string|Mustache_Source $source
|
|
|
|
* @param Mustache_Cache $cache (default: null)
|
|
|
|
*
|
|
|
|
* @return Mustache_Template
|
|
|
|
*/
|
|
|
|
private function loadSource($source, Mustache_Cache $cache = null)
|
|
|
|
{
|
|
|
|
$className = $this->getTemplateClassName($source);
|
|
|
|
|
|
|
|
if (!isset($this->templates[$className])) {
|
|
|
|
if ($cache === null) {
|
|
|
|
$cache = $this->getCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!class_exists($className, false)) {
|
|
|
|
if (!$cache->load($className)) {
|
|
|
|
$compiled = $this->compile($source);
|
|
|
|
$cache->cache($className, $compiled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->log(
|
|
|
|
Mustache_Logger::DEBUG,
|
|
|
|
'Instantiating template: "{className}"',
|
|
|
|
array('className' => $className)
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->templates[$className] = new $className($this);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->templates[$className];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to tokenize a Mustache template.
|
|
|
|
*
|
|
|
|
* @see Mustache_Tokenizer::scan
|
|
|
|
*
|
|
|
|
* @param string $source
|
|
|
|
*
|
|
|
|
* @return array Tokens
|
|
|
|
*/
|
|
|
|
private function tokenize($source)
|
|
|
|
{
|
|
|
|
return $this->getTokenizer()->scan($source, $this->delimiters);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to parse a Mustache template.
|
|
|
|
*
|
|
|
|
* @see Mustache_Parser::parse
|
|
|
|
*
|
|
|
|
* @param string $source
|
|
|
|
*
|
|
|
|
* @return array Token tree
|
|
|
|
*/
|
|
|
|
private function parse($source)
|
|
|
|
{
|
|
|
|
$parser = $this->getParser();
|
|
|
|
$parser->setPragmas($this->getPragmas());
|
|
|
|
|
|
|
|
return $parser->parse($this->tokenize($source));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to compile a Mustache template.
|
|
|
|
*
|
|
|
|
* @see Mustache_Compiler::compile
|
|
|
|
*
|
|
|
|
* @param string|Mustache_Source $source
|
|
|
|
*
|
|
|
|
* @return string generated Mustache template class code
|
|
|
|
*/
|
|
|
|
private function compile($source)
|
|
|
|
{
|
|
|
|
$name = $this->getTemplateClassName($source);
|
|
|
|
|
|
|
|
$this->log(
|
|
|
|
Mustache_Logger::INFO,
|
|
|
|
'Compiling template to "{className}" class',
|
|
|
|
array('className' => $name)
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($source instanceof Mustache_Source) {
|
|
|
|
$source = $source->getSource();
|
|
|
|
}
|
|
|
|
$tree = $this->parse($source);
|
|
|
|
|
|
|
|
$compiler = $this->getCompiler();
|
|
|
|
$compiler->setPragmas($this->getPragmas());
|
|
|
|
|
|
|
|
return $compiler->compile($source, $tree, $name, isset($this->escape), $this->charset, $this->strictCallables, $this->entityFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a log record if logging is enabled.
|
|
|
|
*
|
|
|
|
* @param int $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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|