MDL-60286 lib: Update mustache to 2.12.0
authorAdrian Greeve <adrian@moodle.com>
Fri, 6 Oct 2017 05:54:39 +0000 (13:54 +0800)
committerAdrian Greeve <adrian@moodle.com>
Mon, 9 Oct 2017 01:43:47 +0000 (09:43 +0800)
34 files changed:
lib/mustache/src/Mustache/Autoloader.php
lib/mustache/src/Mustache/Cache.php
lib/mustache/src/Mustache/Cache/AbstractCache.php
lib/mustache/src/Mustache/Cache/FilesystemCache.php
lib/mustache/src/Mustache/Cache/NoopCache.php
lib/mustache/src/Mustache/Compiler.php
lib/mustache/src/Mustache/Context.php
lib/mustache/src/Mustache/Engine.php
lib/mustache/src/Mustache/Exception.php
lib/mustache/src/Mustache/Exception/InvalidArgumentException.php
lib/mustache/src/Mustache/Exception/LogicException.php
lib/mustache/src/Mustache/Exception/RuntimeException.php
lib/mustache/src/Mustache/Exception/SyntaxException.php
lib/mustache/src/Mustache/Exception/UnknownFilterException.php
lib/mustache/src/Mustache/Exception/UnknownHelperException.php
lib/mustache/src/Mustache/Exception/UnknownTemplateException.php
lib/mustache/src/Mustache/HelperCollection.php
lib/mustache/src/Mustache/LambdaHelper.php
lib/mustache/src/Mustache/Loader.php
lib/mustache/src/Mustache/Loader/ArrayLoader.php
lib/mustache/src/Mustache/Loader/CascadingLoader.php
lib/mustache/src/Mustache/Loader/FilesystemLoader.php
lib/mustache/src/Mustache/Loader/InlineLoader.php
lib/mustache/src/Mustache/Loader/MutableLoader.php
lib/mustache/src/Mustache/Loader/ProductionFilesystemLoader.php [new file with mode: 0644]
lib/mustache/src/Mustache/Loader/StringLoader.php
lib/mustache/src/Mustache/Logger.php
lib/mustache/src/Mustache/Logger/AbstractLogger.php
lib/mustache/src/Mustache/Logger/StreamLogger.php
lib/mustache/src/Mustache/Parser.php
lib/mustache/src/Mustache/Source.php [new file with mode: 0644]
lib/mustache/src/Mustache/Source/FilesystemSource.php [new file with mode: 0644]
lib/mustache/src/Mustache/Template.php
lib/mustache/src/Mustache/Tokenizer.php

index b16ac14..e8ea3f4 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -16,6 +16,14 @@ class Mustache_Autoloader
 {
     private $baseDir;
 
+    /**
+     * An array where the key is the baseDir and the key is an instance of this
+     * class.
+     *
+     * @var array
+     */
+    private static $instances;
+
     /**
      * Autoloader constructor.
      *
@@ -45,7 +53,13 @@ class Mustache_Autoloader
      */
     public static function register($baseDir = null)
     {
-        $loader = new self($baseDir);
+        $key = $baseDir ? $baseDir : 0;
+
+        if (!isset(self::$instances[$key])) {
+            self::$instances[$key] = new self($baseDir);
+        }
+
+        $loader = self::$instances[$key];
         spl_autoload_register(array($loader, 'autoload'));
 
         return $loader;
index 7b465ab..3b5b3f1 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 495090b..365eafa 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 0dbe8f9..3e742b7 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -108,9 +108,11 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache
             );
 
             @mkdir($dirName, 0777, true);
+            // @codeCoverageIgnoreStart
             if (!is_dir($dirName)) {
                 throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName));
             }
+            // @codeCoverageIgnoreEnd
         }
 
         return $dirName;
@@ -143,13 +145,17 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache
                 return;
             }
 
+            // @codeCoverageIgnoreStart
             $this->log(
                 Mustache_Logger::ERROR,
                 'Unable to rename Mustache temp cache file: "{tempName}" -> "{fileName}"',
                 array('tempName' => $tempFile, 'fileName' => $fileName)
             );
+            // @codeCoverageIgnoreEnd
         }
 
+        // @codeCoverageIgnoreStart
         throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName));
+        // @codeCoverageIgnoreEnd
     }
 }
index ca0007d..ed9eec9 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 2a831d6..610369e 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -191,7 +191,6 @@ class Mustache_Compiler
             {
                 $this->lambdaHelper = new Mustache_LambdaHelper($this->mustache, $context);
                 $buffer = \'\';
-                $blocksContext = array();
         %s
 
                 return $buffer;
@@ -207,7 +206,6 @@ class Mustache_Compiler
             public function renderInternal(Mustache_Context $context, $indent = \'\')
             {
                 $buffer = \'\';
-                $blocksContext = array();
         %s
 
                 return $buffer;
@@ -240,10 +238,11 @@ class Mustache_Compiler
         $blockFunction = $context->findInBlock(%s);
         if (is_callable($blockFunction)) {
             $buffer .= call_user_func($blockFunction, $context);
-        } else {%s
-        }
+        %s}
     ';
 
+    const BLOCK_VAR_ELSE = '} else {%s';
+
     /**
      * Generate Mustache Template inheritance block variable PHP source.
      *
@@ -261,10 +260,15 @@ class Mustache_Compiler
     {
         $id = var_export($id, true);
 
-        return sprintf($this->prepare(self::BLOCK_VAR, $level), $id, $this->walk($nodes, $level));
+        $else = $this->walk($nodes, $level);
+        if ($else !== '') {
+            $else = sprintf($this->prepare(self::BLOCK_VAR_ELSE, $level + 1, false, true), $else);
+        }
+
+        return sprintf($this->prepare(self::BLOCK_VAR, $level), $id, $else);
     }
 
-    const BLOCK_ARG = '$blocksContext[%s] = array($this, \'block%s\');';
+    const BLOCK_ARG = '%s => array($this, \'block%s\'),';
 
     /**
      * Generate Mustache Template inheritance block argument PHP source.
@@ -285,14 +289,13 @@ class Mustache_Compiler
         $keystr = var_export($key, true);
         $id = var_export($id, true);
 
-        return sprintf($this->prepare(self::BLOCK_ARG, 1), $id, $key);
+        return sprintf($this->prepare(self::BLOCK_ARG, $level), $id, $key);
     }
 
     const BLOCK_FUNCTION = '
         public function block%s($context)
         {
-            $indent = $buffer = \'\';
-            $blocksContext = array();%s
+            $indent = $buffer = \'\';%s
 
             return $buffer;
         }
@@ -327,7 +330,6 @@ class Mustache_Compiler
         private function section%s(Mustache_Context $context, $indent, $value)
         {
             $buffer = \'\';
-            $blocksContext = array();
 
             if (%s) {
                 $source = %s;
@@ -363,11 +365,10 @@ class Mustache_Compiler
      * @param string   $otag    Current Mustache opening tag
      * @param string   $ctag    Current Mustache closing tag
      * @param int      $level
-     * @param bool     $arg     (default: false)
      *
      * @return string Generated section PHP source code
      */
-    private function section($nodes, $id, $filters, $start, $end, $otag, $ctag, $level, $arg = false)
+    private function section($nodes, $id, $filters, $start, $end, $otag, $ctag, $level)
     {
         $source   = var_export(substr($this->source, $start, $end - $start), true);
         $callable = $this->getCallable();
@@ -387,15 +388,11 @@ class Mustache_Compiler
             $this->sections[$key] = sprintf($this->prepare(self::SECTION), $key, $callable, $source, $helper, $delims, $this->walk($nodes, 2));
         }
 
-        if ($arg === true) {
-            return $key;
-        } else {
-            $method  = $this->getFindMethod($id);
-            $id      = var_export($id, true);
-            $filters = $this->getFilters($filters, $level);
+        $method  = $this->getFindMethod($id);
+        $id      = var_export($id, true);
+        $filters = $this->getFilters($filters, $level);
 
-            return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key);
-        }
+        return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key);
     }
 
     const INVERTED_SECTION = '
@@ -457,15 +454,20 @@ class Mustache_Compiler
     }
 
     const PARENT = '
-        %s
-
         if ($parent = $this->mustache->loadPartial(%s)) {
-            $context->pushBlockContext($blocksContext);
+            $context->pushBlockContext(array(%s
+            ));
             $buffer .= $parent->renderInternal($context, $indent);
             $context->popBlockContext();
         }
     ';
 
+    const PARENT_NO_CONTEXT = '
+        if ($parent = $this->mustache->loadPartial(%s)) {
+            $buffer .= $parent->renderInternal($context, $indent);
+        }
+    ';
+
     /**
      * Generate Mustache Template inheritance parent call PHP source.
      *
@@ -480,11 +482,14 @@ class Mustache_Compiler
     {
         $realChildren = array_filter($children, array(__CLASS__, 'onlyBlockArgs'));
 
+        if (empty($realChildren)) {
+            return sprintf($this->prepare(self::PARENT_NO_CONTEXT, $level), var_export($id, true));
+        }
+
         return sprintf(
             $this->prepare(self::PARENT, $level),
-            $this->walk($realChildren, $level),
             var_export($id, true),
-            var_export($indent, true)
+            $this->walk($realChildren, $level + 1)
         );
     }
 
@@ -621,7 +626,7 @@ class Mustache_Compiler
     /**
      * Select the appropriate Context `find` method for a given $id.
      *
-     * The return value will be one of `find`, `findDot` or `last`.
+     * The return value will be one of `find`, `findDot`, `findAnchoredDot` or `last`.
      *
      * @see Mustache_Context::find
      * @see Mustache_Context::findDot
index f59faea..69c02e0 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 856d4ef..9110977 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -23,7 +23,7 @@
  */
 class Mustache_Engine
 {
-    const VERSION        = '2.11.1';
+    const VERSION        = '2.12.0';
     const SPEC_VERSION   = '1.1.2';
 
     const PRAGMA_FILTERS      = 'FILTERS';
@@ -54,6 +54,7 @@ class Mustache_Engine
     private $logger;
     private $strictCallables = false;
     private $pragmas = array();
+    private $delimiters;
 
     // Services
     private $tokenizer;
@@ -81,6 +82,14 @@ class Mustache_Engine
      *         // 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'),
      *
@@ -133,6 +142,10 @@ class Mustache_Engine
     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'];
         }
 
@@ -191,6 +204,10 @@ class Mustache_Engine
             $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])) {
@@ -589,22 +606,43 @@ class Mustache_Engine
     /**
      * Helper method to generate a Mustache template class.
      *
-     * @param string $source
+     * 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)
     {
-        return $this->templateClassPrefix . md5(sprintf(
-            'version:%s,escape:%s,entity_flags:%i,charset:%s,strict_callables:%s,pragmas:%s,source:%s',
-            self::VERSION,
-            isset($this->escape) ? 'custom' : 'default',
-            $this->entityFlags,
-            $this->charset,
-            $this->strictCallables ? 'true' : 'false',
-            implode(' ', $this->getPragmas()),
-            $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);
     }
 
     /**
@@ -681,8 +719,8 @@ class Mustache_Engine
      * @see Mustache_Engine::loadPartial
      * @see Mustache_Engine::loadLambda
      *
-     * @param string         $source
-     * @param Mustache_Cache $cache  (default: null)
+     * @param string|Mustache_Source $source
+     * @param Mustache_Cache         $cache  (default: null)
      *
      * @return Mustache_Template
      */
@@ -725,7 +763,7 @@ class Mustache_Engine
      */
     private function tokenize($source)
     {
-        return $this->getTokenizer()->scan($source);
+        return $this->getTokenizer()->scan($source, $this->delimiters);
     }
 
     /**
@@ -750,13 +788,12 @@ class Mustache_Engine
      *
      * @see Mustache_Compiler::compile
      *
-     * @param string $source
+     * @param string|Mustache_Source $source
      *
      * @return string generated Mustache template class code
      */
     private function compile($source)
     {
-        $tree = $this->parse($source);
         $name = $this->getTemplateClassName($source);
 
         $this->log(
@@ -765,6 +802,11 @@ class Mustache_Engine
             array('className' => $name)
         );
 
+        if ($source instanceof Mustache_Source) {
+            $source = $source->getSource();
+        }
+        $tree = $this->parse($source);
+
         $compiler = $this->getCompiler();
         $compiler->setPragmas($this->getPragmas());
 
index 66bd6bd..d4001a9 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 46b200c..becf2ed 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 8e75e7e..b2424d6 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 9a7b90b..b6369f4 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 4fcb39d..b1879a3 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -27,7 +27,7 @@ class Mustache_Exception_SyntaxException extends LogicException implements Musta
         if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
             parent::__construct($msg, 0, $previous);
         } else {
-            parent::__construct($msg);
+            parent::__construct($msg); // @codeCoverageIgnore
         }
     }
 
index 44505e4..0651c17 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -27,7 +27,7 @@ class Mustache_Exception_UnknownFilterException extends UnexpectedValueException
         if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
             parent::__construct($message, 0, $previous);
         } else {
-            parent::__construct($message);
+            parent::__construct($message); // @codeCoverageIgnore
         }
     }
 
index e1bc4d2..193be78 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -27,7 +27,7 @@ class Mustache_Exception_UnknownHelperException extends InvalidArgumentException
         if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
             parent::__construct($message, 0, $previous);
         } else {
-            parent::__construct($message);
+            parent::__construct($message); // @codeCoverageIgnore
         }
     }
 
index 0c37796..32a778a 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -27,7 +27,7 @@ class Mustache_Exception_UnknownTemplateException extends InvalidArgumentExcepti
         if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
             parent::__construct($message, 0, $previous);
         } else {
-            parent::__construct($message);
+            parent::__construct($message); // @codeCoverageIgnore
         }
     }
 
index 86c56b7..5d8f73c 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 1d203d5..e93dbfa 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index c5e1a19..23adba1 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -21,7 +21,7 @@ interface Mustache_Loader
      *
      * @param string $name
      *
-     * @return string Mustache Template source
+     * @return string|Mustache_Source Mustache Template source
      */
     public function load($name);
 }
index c0d6a4d..4276493 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index b4726bc..3fb6353 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index a313751..e366df7 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index f6d4b17..ae297fe 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index f228d90..57fe5be 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
diff --git a/lib/mustache/src/Mustache/Loader/ProductionFilesystemLoader.php b/lib/mustache/src/Mustache/Loader/ProductionFilesystemLoader.php
new file mode 100644 (file)
index 0000000..e735332
--- /dev/null
@@ -0,0 +1,86 @@
+<?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.
+ */
+
+/**
+ * Mustache Template production filesystem Loader implementation.
+ *
+ * A production-ready FilesystemLoader, which doesn't require reading a file if it already exists in the template cache.
+ *
+ * {@inheritdoc}
+ */
+class Mustache_Loader_ProductionFilesystemLoader extends Mustache_Loader_FilesystemLoader
+{
+    private $statProps;
+
+    /**
+     * Mustache production filesystem Loader constructor.
+     *
+     * Passing an $options array allows overriding certain Loader options during instantiation:
+     *
+     *     $options = array(
+     *         // The filename extension used for Mustache templates. Defaults to '.mustache'
+     *         'extension' => '.ms',
+     *         'stat_props' => array('size', 'mtime'),
+     *     );
+     *
+     * Specifying 'stat_props' overrides the stat properties used to invalidate the template cache. By default, this
+     * uses 'mtime' and 'size', but this can be set to any of the properties supported by stat():
+     *
+     *     http://php.net/manual/en/function.stat.php
+     *
+     * You can also disable filesystem stat entirely:
+     *
+     *     $options = array('stat_props' => null);
+     *
+     * But with great power comes great responsibility. Namely, if you disable stat-based cache invalidation,
+     * YOU MUST CLEAR THE TEMPLATE CACHE YOURSELF when your templates change. Make it part of your build or deploy
+     * process so you don't forget!
+     *
+     * @throws Mustache_Exception_RuntimeException if $baseDir does not exist.
+     *
+     * @param string $baseDir Base directory containing Mustache template files.
+     * @param array  $options Array of Loader options (default: array())
+     */
+    public function __construct($baseDir, array $options = array())
+    {
+        parent::__construct($baseDir, $options);
+
+        if (array_key_exists('stat_props', $options)) {
+            if (empty($options['stat_props'])) {
+                $this->statProps = array();
+            } else {
+                $this->statProps = $options['stat_props'];
+            }
+        } else {
+            $this->statProps = array('size', 'mtime');
+        }
+    }
+
+    /**
+     * Helper function for loading a Mustache file by name.
+     *
+     * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
+     *
+     * @param string $name
+     *
+     * @return Mustache_Source Mustache Template source
+     */
+    protected function loadFile($name)
+    {
+        $fileName = $this->getFileName($name);
+
+        if (!file_exists($fileName)) {
+            throw new Mustache_Exception_UnknownTemplateException($name);
+        }
+
+        return new Mustache_Source_FilesystemSource($fileName, $this->statProps);
+    }
+}
index 79b616b..7012c03 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 324a7ce..cb4037a 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 64bdf66..a169f9c 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index efb3231..402a148 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index adefebd..c36a84a 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
diff --git a/lib/mustache/src/Mustache/Source.php b/lib/mustache/src/Mustache/Source.php
new file mode 100644 (file)
index 0000000..278c2cb
--- /dev/null
@@ -0,0 +1,40 @@
+<?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.
+ */
+
+/**
+ * Mustache template Source interface.
+ */
+interface Mustache_Source
+{
+    /**
+     * Get the Source key (used to generate the compiled class name).
+     *
+     * This must return a distinct key for each template source. For example, an
+     * MD5 hash of the template contents would probably do the trick. The
+     * ProductionFilesystemLoader uses mtime and file path. If your production
+     * source directory is under version control, you could use the current Git
+     * rev and the file path...
+     *
+     * @throws RuntimeException when a source file cannot be read
+     *
+     * @return string
+     */
+    public function getKey();
+
+    /**
+     * Get the template Source.
+     *
+     * @throws RuntimeException when a source file cannot be read
+     *
+     * @return string
+     */
+    public function getSource();
+}
diff --git a/lib/mustache/src/Mustache/Source/FilesystemSource.php b/lib/mustache/src/Mustache/Source/FilesystemSource.php
new file mode 100644 (file)
index 0000000..1284ac7
--- /dev/null
@@ -0,0 +1,77 @@
+<?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.
+ */
+
+/**
+ * Mustache template Filesystem Source.
+ *
+ * This template Source uses stat() to generate the Source key, so that using
+ * pre-compiled templates doesn't require hitting the disk to read the source.
+ * It is more suitable for production use, and is used by default in the
+ * ProductionFilesystemLoader.
+ */
+class Mustache_Source_FilesystemSource implements Mustache_Source
+{
+    private $fileName;
+    private $statProps;
+    private $stat;
+
+    /**
+     * Filesystem Source constructor.
+     *
+     * @param string $fileName
+     * @param array  $statProps
+     */
+    public function __construct($fileName, array $statProps)
+    {
+        $this->fileName = $fileName;
+        $this->statProps = $statProps;
+    }
+
+    /**
+     * Get the Source key (used to generate the compiled class name).
+     *
+     * @throws RuntimeException when a source file cannot be read
+     *
+     * @return string
+     */
+    public function getKey()
+    {
+        $chunks = array(
+            'fileName' => $this->fileName,
+        );
+
+        if (!empty($this->statProps)) {
+            if (!isset($this->stat)) {
+                $this->stat = @stat($this->fileName);
+            }
+
+            if ($this->stat === false) {
+                throw new RuntimeException(sprintf('Failed to read source file "%s".', $this->fileName));
+            }
+
+            foreach ($this->statProps as $prop) {
+                $chunks[$prop] = $this->stat[$prop];
+            }
+        }
+
+        return json_encode($chunks);
+    }
+
+    /**
+     * Get the template Source.
+     *
+     * @return string
+     */
+    public function getSource()
+    {
+        return file_get_contents($this->fileName);
+    }
+}
index 2b7771c..4de8239 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
index 27e4d05..b1f3d73 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * This file is part of Mustache.php.
  *
- * (c) 2010-2016 Justin Hileman
+ * (c) 2010-2017 Justin Hileman
  *
  * For the full copyright and license information, please view the LICENSE
  * file that was distributed with this source code.
@@ -91,11 +91,14 @@ class Mustache_Tokenizer
     {
         // Setting mbstring.func_overload makes things *really* slow.
         // Let's do everyone a favor and scan this string as ASCII instead.
+        //
+        // @codeCoverageIgnoreStart
         $encoding = null;
         if (function_exists('mb_internal_encoding') && ini_get('mbstring.func_overload') & 2) {
             $encoding = mb_internal_encoding();
             mb_internal_encoding('ASCII');
         }
+        // @codeCoverageIgnoreEnd
 
         $this->reset();
 
@@ -202,9 +205,11 @@ class Mustache_Tokenizer
         $this->flushBuffer();
 
         // Restore the user's encoding...
+        // @codeCoverageIgnoreStart
         if ($encoding) {
             mb_internal_encoding($encoding);
         }
+        // @codeCoverageIgnoreEnd
 
         return $this->tokens;
     }