A super easy PHP Framework for web development!
				https://github.com/exacti/phacil-framework
			
			
		
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							829 lines
						
					
					
						
							25 KiB
						
					
					
				
			
		
		
	
	
							829 lines
						
					
					
						
							25 KiB
						
					
					
				<?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
 | 
						|
{
 | 
						|
    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);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 |