From 6634f44ca625ff8a49146a334daf25f59a042ce8 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Thu, 5 Sep 2013 14:23:23 -0400 Subject: [PATCH 01/15] Explicitly set timezone to UTC for tests --- test/bootstrap.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/bootstrap.php b/test/bootstrap.php index 91f654a..2399f38 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +date_default_timezone_set('UTC'); + require dirname(__FILE__).'/../src/Mustache/Autoloader.php'; Mustache_Autoloader::register(); From 60338e495656f3735b82dc8e44c0c2dbe23cd799 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Thu, 5 Sep 2013 17:07:38 -0400 Subject: [PATCH 02/15] Extract cache interface Refactoring to allow for alternative cache implementations. Includes implementations for the default noop (i.e. un-cached) behavior and a filesystem-based cache whose configuration is consistent with the existing Mustache_Engine constructor. Includes updated and new tests. --- src/Mustache/Cache.php | 7 + src/Mustache/Cache/FilesystemCache.php | 51 +++++++ src/Mustache/Cache/NoopCache.php | 7 + src/Mustache/Engine.php | 141 +++++++----------- .../Test/Cache/FilesystemCacheTest.php | 58 +++++++ test/Mustache/Test/EngineTest.php | 12 +- 6 files changed, 181 insertions(+), 95 deletions(-) create mode 100644 src/Mustache/Cache.php create mode 100644 src/Mustache/Cache/FilesystemCache.php create mode 100644 src/Mustache/Cache/NoopCache.php create mode 100644 test/Mustache/Test/Cache/FilesystemCacheTest.php diff --git a/src/Mustache/Cache.php b/src/Mustache/Cache.php new file mode 100644 index 0000000..a9ab043 --- /dev/null +++ b/src/Mustache/Cache.php @@ -0,0 +1,7 @@ +directory = $directory; + $this->fileMode = $fileMode; + } + + public function get($key) + { + $fileName = $this->getCacheFilename($key); + return (is_file($fileName)) + ? file_get_contents($fileName) + : null; + } + + public function put($key, $value) + { + $fileName = $this->getCacheFilename($key); + $dirName = dirname($fileName); + if (!is_dir($dirName)) { + @mkdir($dirName, 0777, true); + if (!is_dir($dirName)) { + throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName)); + } + + } + + $tempFile = tempnam($dirName, basename($fileName)); + if (false !== @file_put_contents($tempFile, $value)) { + if (@rename($tempFile, $fileName)) { + $mode = isset($this->fileMode) ? $this->fileMode : (0666 & ~umask()); + @chmod($fileName, $mode); + + return; + } + } + + throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName)); + } + + protected function getCacheFilename($name) + { + return sprintf('%s/%s.php', $this->directory, md5($name)); + } +} diff --git a/src/Mustache/Cache/NoopCache.php b/src/Mustache/Cache/NoopCache.php new file mode 100644 index 0000000..3d722ab --- /dev/null +++ b/src/Mustache/Cache/NoopCache.php @@ -0,0 +1,7 @@ + '__MyTemplates_', * + * // A Mustache cache instance. Uses a NoopCache if not specified. + * 'cacher' => new Mustache_Cache_FilesystemCache(dirname(__FILE__).'/tmp/cache/mustache'), + * * // A cache directory for compiled templates. Mustache will not cache templates unless this is set * 'cache' => dirname(__FILE__).'/tmp/cache/mustache', * @@ -111,12 +113,13 @@ class Mustache_Engine $this->templateClassPrefix = $options['template_class_prefix']; } - if (isset($options['cache'])) { - $this->cache = $options['cache']; - } - - if (isset($options['cache_file_mode'])) { - $this->cacheFileMode = $options['cache_file_mode']; + if (isset($options['cacher'])) { + $this->cache = $options['cacher']; + } else if (isset($options['cache'])) { + $this->cache = new Mustache_Cache_FilesystemCache( + $options['cache'], + $options['cache_file_mode'] + ); } if (isset($options['loader'])) { @@ -479,6 +482,38 @@ class Mustache_Engine return $this->compiler; } + /** + * Set the Mustache Tokenizer instance. + * + * @param Mustache_Cache $cache + */ + public function setCache(Mustache_Cache $cache) + { + $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->cache = new Mustache_Cache_NoopCache(); + + $this->log( + Mustache_Logger::WARNING, + 'Template cache disabled', + array() + ); + } + + return $this->cache; + } + /** * Helper method to generate a Mustache template class. * @@ -580,27 +615,17 @@ class Mustache_Engine if (!isset($this->templates[$className])) { if (!class_exists($className, false)) { - if ($fileName = $this->getCacheFilename($source)) { - if (!is_file($fileName)) { - $this->log( - Mustache_Logger::DEBUG, - 'Writing "{className}" class to template cache: "{fileName}"', - array('className' => $className, 'fileName' => $fileName) - ); - - $this->writeCacheFile($fileName, $this->compile($source)); - } - - require_once $fileName; - } else { + $cached = $this->getCache()->get($source); + if (!$cached) { $this->log( - Mustache_Logger::WARNING, - 'Template cache disabled, evaluating "{className}" class at runtime', + Mustache_Logger::DEBUG, + 'Writing "{className}" class to template cache', array('className' => $className) ); - - eval('?>'.$this->compile($source)); + $cached = $this->compile($source); + $this->getCache()->put($source, $cached); } + eval('?>'.$cached); } $this->log( @@ -666,72 +691,6 @@ class Mustache_Engine return $this->getCompiler()->compile($source, $tree, $name, isset($this->escape), $this->charset, $this->strictCallables, $this->entityFlags); } - /** - * Helper method to generate a Mustache Template class cache filename. - * - * @param string $source - * - * @return string Mustache Template class cache filename - */ - private function getCacheFilename($source) - { - if ($this->cache) { - return sprintf('%s/%s.php', $this->cache, $this->getTemplateClassName($source)); - } - } - - /** - * Helper method to dump a generated Mustache Template subclass to the file cache. - * - * @throws Mustache_Exception_RuntimeException if unable to create the cache directory or write to $fileName. - * - * @param string $fileName - * @param string $source - * - * @codeCoverageIgnore - */ - private function writeCacheFile($fileName, $source) - { - $dirName = dirname($fileName); - if (!is_dir($dirName)) { - $this->log( - Mustache_Logger::INFO, - 'Creating Mustache template cache directory: "{dirName}"', - array('dirName' => $dirName) - ); - - @mkdir($dirName, 0777, true); - if (!is_dir($dirName)) { - throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName)); - } - - } - - $this->log( - Mustache_Logger::DEBUG, - 'Caching compiled template to "{fileName}"', - array('fileName' => $fileName) - ); - - $tempFile = tempnam($dirName, basename($fileName)); - if (false !== @file_put_contents($tempFile, $source)) { - if (@rename($tempFile, $fileName)) { - $mode = isset($this->cacheFileMode) ? $this->cacheFileMode : (0666 & ~umask()); - @chmod($fileName, $mode); - - return; - } - - $this->log( - Mustache_Logger::ERROR, - 'Unable to rename Mustache temp cache file: "{tempName}" -> "{fileName}"', - array('tempName' => $tempFile, 'fileName' => $fileName) - ); - } - - throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName)); - } - /** * Add a log record if logging is enabled. * diff --git a/test/Mustache/Test/Cache/FilesystemCacheTest.php b/test/Mustache/Test/Cache/FilesystemCacheTest.php new file mode 100644 index 0000000..ae70e73 --- /dev/null +++ b/test/Mustache/Test/Cache/FilesystemCacheTest.php @@ -0,0 +1,58 @@ +get($key); + + $this->assertNull($cached); + } + + public function testCachePut() + { + $key = 'some key'; + $value = 'some value'; + $cache = new Mustache_Cache_FilesystemCache(self::$tempDir);; + $cache->put($key, $value); + $cached = $cache->get($key); + + $this->assertEquals($cached, $value); + } + + private static function rmdir($path) + { + $path = rtrim($path, '/').'/'; + $handle = opendir($path); + while (($file = readdir($handle)) !== false) { + if ($file == '.' || $file == '..') { + continue; + } + + $fullpath = $path.$file; + if (is_dir($fullpath)) { + self::rmdir($fullpath); + } else { + unlink($fullpath); + } + } + + closedir($handle); + rmdir($path); + } +} diff --git a/test/Mustache/Test/EngineTest.php b/test/Mustache/Test/EngineTest.php index 5c00821..5b5402b 100644 --- a/test/Mustache/Test/EngineTest.php +++ b/test/Mustache/Test/EngineTest.php @@ -58,6 +58,7 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase $this->assertTrue($mustache->hasHelper('foo')); $this->assertTrue($mustache->hasHelper('bar')); $this->assertFalse($mustache->hasHelper('baz')); + $this->assertInstanceOf('Mustache_Cache_FilesystemCache', $mustache->getCache()); } public static function getFoo() @@ -95,6 +96,7 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase $parser = new Mustache_Parser; $compiler = new Mustache_Compiler; $mustache = new Mustache_Engine; + $cache = new Mustache_Cache_FilesystemCache(sys_get_temp_dir()); $this->assertNotSame($logger, $mustache->getLogger()); $mustache->setLogger($logger); @@ -119,6 +121,10 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase $this->assertNotSame($compiler, $mustache->getCompiler()); $mustache->setCompiler($compiler); $this->assertSame($compiler, $mustache->getCompiler()); + + $this->assertNotSame($cache, $mustache->getCache()); + $mustache->setCache($cache); + $this->assertSame($cache, $mustache->getCache()); } /** @@ -134,10 +140,8 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase $source = '{{ foo }}'; $template = $mustache->loadTemplate($source); $className = $mustache->getTemplateClassName($source); - $fileName = self::$tempDir . '/' . $className . '.php'; + $this->assertInstanceOf($className, $template); - $this->assertFileExists($fileName); - $this->assertContains("\nclass $className extends Mustache_Template", file_get_contents($fileName)); } /** @@ -290,7 +294,7 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase $result = $mustache->render('{{ foo }}', array('foo' => 'FOO')); $this->assertEquals('FOO', $result); - $this->assertContains('WARNING: Template cache disabled, evaluating', file_get_contents($name)); + $this->assertContains('WARNING: Template cache disabled', file_get_contents($name)); } public function testLoggingIsNotTooAnnoying() From 3e876fd9846a911d981621909a546042b7ded164 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Thu, 5 Sep 2013 17:30:28 -0400 Subject: [PATCH 03/15] Fix build - explicit config key check --- src/Mustache/Engine.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index 1becac9..90ffddc 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -116,9 +116,12 @@ class Mustache_Engine if (isset($options['cacher'])) { $this->cache = $options['cacher']; } else if (isset($options['cache'])) { + $cacheFileMode = isset($options['cache_file_mode']) + ? $options['cache_file_mode'] + : null; $this->cache = new Mustache_Cache_FilesystemCache( $options['cache'], - $options['cache_file_mode'] + $cacheFileMode ); } From 71eaed27783cfdaa962a85268fb0a0b048e14064 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Thu, 5 Sep 2013 18:16:00 -0400 Subject: [PATCH 04/15] Cleanup cache initialization from options --- src/Mustache/Engine.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index 90ffddc..10cbaf8 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -55,7 +55,8 @@ class Mustache_Engine * // A Mustache cache instance. Uses a NoopCache if not specified. * 'cacher' => new Mustache_Cache_FilesystemCache(dirname(__FILE__).'/tmp/cache/mustache'), * - * // A cache directory for compiled templates. Mustache will not cache templates unless this is set + * // 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 @@ -113,16 +114,15 @@ class Mustache_Engine $this->templateClassPrefix = $options['template_class_prefix']; } - if (isset($options['cacher'])) { - $this->cache = $options['cacher']; - } else if (isset($options['cache'])) { - $cacheFileMode = isset($options['cache_file_mode']) - ? $options['cache_file_mode'] - : null; - $this->cache = new Mustache_Cache_FilesystemCache( - $options['cache'], - $cacheFileMode - ); + 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['loader'])) { From 94cd72bfd4b970b21f528525bba3c21bf388ecad Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Thu, 5 Sep 2013 18:56:43 -0400 Subject: [PATCH 05/15] Restore original eval vs. require class loading Pushing the responsibility of class loading onto the `Mustache_Cache` implementation and changing the semantics of get/put to load/cache. --- src/Mustache/Cache.php | 4 +- src/Mustache/Cache/FilesystemCache.php | 64 +++++++++++-------- src/Mustache/Cache/NoopCache.php | 11 +++- src/Mustache/Engine.php | 13 +--- .../Test/Cache/FilesystemCacheTest.php | 12 ++-- 5 files changed, 59 insertions(+), 45 deletions(-) diff --git a/src/Mustache/Cache.php b/src/Mustache/Cache.php index a9ab043..4797cdf 100644 --- a/src/Mustache/Cache.php +++ b/src/Mustache/Cache.php @@ -2,6 +2,6 @@ interface Mustache_Cache { - public function get($key); - public function put($key, $value); + public function load($key); + public function cache($key, $value); } diff --git a/src/Mustache/Cache/FilesystemCache.php b/src/Mustache/Cache/FilesystemCache.php index 0b3e82c..a79a081 100644 --- a/src/Mustache/Cache/FilesystemCache.php +++ b/src/Mustache/Cache/FilesystemCache.php @@ -11,41 +11,55 @@ class Mustache_Cache_FilesystemCache implements Mustache_Cache $this->fileMode = $fileMode; } - public function get($key) + public function load($key) { $fileName = $this->getCacheFilename($key); - return (is_file($fileName)) - ? file_get_contents($fileName) - : null; + if (!is_file($fileName)) { + return false; + } + + require_once $fileName; + + return true; } - public function put($key, $value) + public function cache($key, $value) { $fileName = $this->getCacheFilename($key); - $dirName = dirname($fileName); - if (!is_dir($dirName)) { - @mkdir($dirName, 0777, true); - if (!is_dir($dirName)) { - throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName)); - } - - } - - $tempFile = tempnam($dirName, basename($fileName)); - if (false !== @file_put_contents($tempFile, $value)) { - if (@rename($tempFile, $fileName)) { - $mode = isset($this->fileMode) ? $this->fileMode : (0666 & ~umask()); - @chmod($fileName, $mode); - - return; - } - } - - throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName)); + $this->writeFile($fileName, $value); + $this->load($key); } protected function getCacheFilename($name) { return sprintf('%s/%s.php', $this->directory, md5($name)); } + + private function buildDirectoryForFilename($fileName) + { + $dirName = dirname($fileName); + if (!is_dir($dirName)) { + @mkdir($dirName, 0777, true); + if (!is_dir($dirName)) { + throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName)); + } + } + return $dirName; + } + + private function writeFile($fileName, $value) + { + $dirName = $this->buildDirectoryForFilename($fileName); + $tempFile = tempnam($dirName, basename($fileName)); + if (false !== @file_put_contents($tempFile, $value)) { + if (@rename($tempFile, $fileName)) { + $mode = isset($this->fileMode) ? $this->fileMode : (0666 & ~umask()); + @chmod($fileName, $mode); + + return $fileName; + } + } + + throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName)); + } } diff --git a/src/Mustache/Cache/NoopCache.php b/src/Mustache/Cache/NoopCache.php index 3d722ab..95fd2d9 100644 --- a/src/Mustache/Cache/NoopCache.php +++ b/src/Mustache/Cache/NoopCache.php @@ -2,6 +2,13 @@ class Mustache_Cache_NoopCache implements Mustache_Cache { - public function get($key) { return null; } - public function put($key, $value) {} + public function load($key) + { + return false; + } + + public function cache($key, $compiled) + { + eval("?>".$compiled); + } } diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index 10cbaf8..1a2fee7 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -618,17 +618,10 @@ class Mustache_Engine if (!isset($this->templates[$className])) { if (!class_exists($className, false)) { - $cached = $this->getCache()->get($source); - if (!$cached) { - $this->log( - Mustache_Logger::DEBUG, - 'Writing "{className}" class to template cache', - array('className' => $className) - ); - $cached = $this->compile($source); - $this->getCache()->put($source, $cached); + if (!$this->getCache()->load($source)) { + $compiled = $this->compile($source); + $this->getCache()->cache($source, $compiled); } - eval('?>'.$cached); } $this->log( diff --git a/test/Mustache/Test/Cache/FilesystemCacheTest.php b/test/Mustache/Test/Cache/FilesystemCacheTest.php index ae70e73..f5ff91f 100644 --- a/test/Mustache/Test/Cache/FilesystemCacheTest.php +++ b/test/Mustache/Test/Cache/FilesystemCacheTest.php @@ -19,20 +19,20 @@ class Mustache_Test_Cache_FilesystemCacheTest extends PHPUnit_Framework_TestCase { $key = 'some key'; $cache = new Mustache_Cache_FilesystemCache(self::$tempDir);; - $cached = $cache->get($key); + $loaded = $cache->load($key); - $this->assertNull($cached); + $this->assertFalse($loaded); } public function testCachePut() { $key = 'some key'; - $value = 'some value'; + $value = 'put($key, $value); - $cached = $cache->get($key); + $cache->cache($key, $value); + $loaded = $cache->load($key); - $this->assertEquals($cached, $value); + $this->assertTrue($loaded); } private static function rmdir($path) From 724cd60cacd02f8ffc2d7cd9c1966d7e71d9bb5c Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Thu, 5 Sep 2013 19:22:13 -0400 Subject: [PATCH 06/15] Restore logging for cache operations `AbstractCache` exposes the ability to set a logger. Default behavior automatically passes the logger reference down to the cache, unless a specific cache instance was provided. --- src/Mustache/Cache/AbstractCache.php | 27 +++++++++++++++++++++++++ src/Mustache/Cache/FilesystemCache.php | 28 +++++++++++++++++++++++++- src/Mustache/Cache/NoopCache.php | 7 ++++++- src/Mustache/Engine.php | 10 ++++----- test/Mustache/Test/EngineTest.php | 2 +- 5 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/Mustache/Cache/AbstractCache.php diff --git a/src/Mustache/Cache/AbstractCache.php b/src/Mustache/Cache/AbstractCache.php new file mode 100644 index 0000000..7120536 --- /dev/null +++ b/src/Mustache/Cache/AbstractCache.php @@ -0,0 +1,27 @@ +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.'); + } + + $this->logger = $logger; + } + + protected function log($level, $message, array $context = array()) + { + if (isset($this->logger)) { + $this->logger->log($level, $message, $context); + } + } +} diff --git a/src/Mustache/Cache/FilesystemCache.php b/src/Mustache/Cache/FilesystemCache.php index a79a081..c6af6ae 100644 --- a/src/Mustache/Cache/FilesystemCache.php +++ b/src/Mustache/Cache/FilesystemCache.php @@ -1,6 +1,6 @@ getCacheFilename($key); + + $this->log( + Mustache_Logger::DEBUG, + 'Writing to template cache: "{fileName}"', + array('fileName' => $fileName) + ); + $this->writeFile($fileName, $value); $this->load($key); } @@ -39,6 +46,12 @@ class Mustache_Cache_FilesystemCache implements Mustache_Cache { $dirName = dirname($fileName); if (!is_dir($dirName)) { + $this->log( + Mustache_Logger::INFO, + 'Creating Mustache template cache directory: "{dirName}"', + array('dirName' => $dirName) + ); + @mkdir($dirName, 0777, true); if (!is_dir($dirName)) { throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName)); @@ -50,6 +63,13 @@ class Mustache_Cache_FilesystemCache implements Mustache_Cache private function writeFile($fileName, $value) { $dirName = $this->buildDirectoryForFilename($fileName); + + $this->log( + Mustache_Logger::DEBUG, + 'Caching compiled template to "{fileName}"', + array('fileName' => $fileName) + ); + $tempFile = tempnam($dirName, basename($fileName)); if (false !== @file_put_contents($tempFile, $value)) { if (@rename($tempFile, $fileName)) { @@ -58,6 +78,12 @@ class Mustache_Cache_FilesystemCache implements Mustache_Cache return $fileName; } + + $this->log( + Mustache_Logger::ERROR, + 'Unable to rename Mustache temp cache file: "{tempName}" -> "{fileName}"', + array('tempName' => $tempFile, 'fileName' => $fileName) + ); } throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName)); diff --git a/src/Mustache/Cache/NoopCache.php b/src/Mustache/Cache/NoopCache.php index 95fd2d9..d717149 100644 --- a/src/Mustache/Cache/NoopCache.php +++ b/src/Mustache/Cache/NoopCache.php @@ -1,6 +1,6 @@ log( + Mustache_Logger::WARNING, + 'Template cache disabled, evaluating class at runtime', + array() + ); eval("?>".$compiled); } } diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index 1a2fee7..ef3e752 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -164,6 +164,10 @@ class Mustache_Engine if (isset($options['strict_callables'])) { $this->strictCallables = $options['strict_callables']; } + + if (!isset($options['cache']) || is_string($options['cache'])) { + $this->getCache()->setLogger($this->getLogger()); + } } /** @@ -506,12 +510,6 @@ class Mustache_Engine { if (!isset($this->cache)) { $this->cache = new Mustache_Cache_NoopCache(); - - $this->log( - Mustache_Logger::WARNING, - 'Template cache disabled', - array() - ); } return $this->cache; diff --git a/test/Mustache/Test/EngineTest.php b/test/Mustache/Test/EngineTest.php index 5b5402b..b63698e 100644 --- a/test/Mustache/Test/EngineTest.php +++ b/test/Mustache/Test/EngineTest.php @@ -294,7 +294,7 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase $result = $mustache->render('{{ foo }}', array('foo' => 'FOO')); $this->assertEquals('FOO', $result); - $this->assertContains('WARNING: Template cache disabled', file_get_contents($name)); + $this->assertContains('WARNING: Template cache disabled, evaluating', file_get_contents($name)); } public function testLoggingIsNotTooAnnoying() From 689be14d0f15634d2da0f031e0a353af658a319c Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Fri, 6 Sep 2013 09:06:26 -0400 Subject: [PATCH 07/15] Invalid documentation --- src/Mustache/Engine.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index ef3e752..bf7f1c5 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -52,9 +52,6 @@ class Mustache_Engine * // The class prefix for compiled templates. Defaults to '__Mustache_'. * 'template_class_prefix' => '__MyTemplates_', * - * // A Mustache cache instance. Uses a NoopCache if not specified. - * 'cacher' => new Mustache_Cache_FilesystemCache(dirname(__FILE__).'/tmp/cache/mustache'), - * * // 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', From 8894d68482511e3b603ef885cee63cabb04a0c42 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Fri, 6 Sep 2013 09:16:15 -0400 Subject: [PATCH 08/15] Use existing temp directory for test --- test/Mustache/Test/EngineTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Mustache/Test/EngineTest.php b/test/Mustache/Test/EngineTest.php index b63698e..f4d102d 100644 --- a/test/Mustache/Test/EngineTest.php +++ b/test/Mustache/Test/EngineTest.php @@ -96,7 +96,7 @@ class Mustache_Test_EngineTest extends PHPUnit_Framework_TestCase $parser = new Mustache_Parser; $compiler = new Mustache_Compiler; $mustache = new Mustache_Engine; - $cache = new Mustache_Cache_FilesystemCache(sys_get_temp_dir()); + $cache = new Mustache_Cache_FilesystemCache(self::$tempDir); $this->assertNotSame($logger, $mustache->getLogger()); $mustache->setLogger($logger); From 1937752519e54509d748d7618058c0380a632d78 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Fri, 6 Sep 2013 09:16:40 -0400 Subject: [PATCH 09/15] Use class name as cache key --- src/Mustache/Cache/FilesystemCache.php | 10 +++++----- src/Mustache/Cache/NoopCache.php | 4 ++-- src/Mustache/Engine.php | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Mustache/Cache/FilesystemCache.php b/src/Mustache/Cache/FilesystemCache.php index c6af6ae..28e6c0c 100644 --- a/src/Mustache/Cache/FilesystemCache.php +++ b/src/Mustache/Cache/FilesystemCache.php @@ -2,12 +2,12 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache { - private $directory; + private $baseDir; private $fileMode; - public function __construct($directory, $fileMode = null) + public function __construct($baseDir, $fileMode = null) { - $this->directory = $directory; + $this->baseDir = $baseDir; $this->fileMode = $fileMode; } @@ -39,7 +39,7 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache protected function getCacheFilename($name) { - return sprintf('%s/%s.php', $this->directory, md5($name)); + return sprintf('%s/%s.php', $this->baseDir, $name); } private function buildDirectoryForFilename($fileName) @@ -76,7 +76,7 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache $mode = isset($this->fileMode) ? $this->fileMode : (0666 & ~umask()); @chmod($fileName, $mode); - return $fileName; + return; } $this->log( diff --git a/src/Mustache/Cache/NoopCache.php b/src/Mustache/Cache/NoopCache.php index d717149..47ed17d 100644 --- a/src/Mustache/Cache/NoopCache.php +++ b/src/Mustache/Cache/NoopCache.php @@ -11,8 +11,8 @@ class Mustache_Cache_NoopCache extends Mustache_Cache_AbstractCache { $this->log( Mustache_Logger::WARNING, - 'Template cache disabled, evaluating class at runtime', - array() + 'Template cache disabled, evaluating "{className}" class at runtime', + array('className' => $className) ); eval("?>".$compiled); } diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index bf7f1c5..84d870b 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -506,7 +506,7 @@ class Mustache_Engine public function getCache() { if (!isset($this->cache)) { - $this->cache = new Mustache_Cache_NoopCache(); + $this->setCache(new Mustache_Cache_NoopCache()); } return $this->cache; @@ -613,9 +613,9 @@ class Mustache_Engine if (!isset($this->templates[$className])) { if (!class_exists($className, false)) { - if (!$this->getCache()->load($source)) { + if (!$this->getCache()->load($className)) { $compiled = $this->compile($source); - $this->getCache()->cache($source, $compiled); + $this->getCache()->cache($className, $compiled); } } From a83ecd70aa960450eba7790dee14ffb2a71767e0 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Fri, 6 Sep 2013 11:50:04 -0400 Subject: [PATCH 10/15] Set logger for cache if not explicitly set --- src/Mustache/Engine.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index 84d870b..f66594f 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -161,10 +161,6 @@ class Mustache_Engine if (isset($options['strict_callables'])) { $this->strictCallables = $options['strict_callables']; } - - if (!isset($options['cache']) || is_string($options['cache'])) { - $this->getCache()->setLogger($this->getLogger()); - } } /** @@ -395,6 +391,10 @@ class Mustache_Engine 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; } @@ -493,6 +493,10 @@ class Mustache_Engine */ public function setCache(Mustache_Cache $cache) { + if (isset($this->logger) && $cache->getLogger() === null) { + $cache->setLogger($this->getLogger()); + } + $this->cache = $cache; } From ae138efb47528c2a8d3a528e7e7a1e8ae4a8bfae Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Fri, 6 Sep 2013 13:34:01 -0400 Subject: [PATCH 11/15] Fix broken build --- src/Mustache/Cache/NoopCache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mustache/Cache/NoopCache.php b/src/Mustache/Cache/NoopCache.php index 47ed17d..1452c64 100644 --- a/src/Mustache/Cache/NoopCache.php +++ b/src/Mustache/Cache/NoopCache.php @@ -12,7 +12,7 @@ class Mustache_Cache_NoopCache extends Mustache_Cache_AbstractCache $this->log( Mustache_Logger::WARNING, 'Template cache disabled, evaluating "{className}" class at runtime', - array('className' => $className) + array('className' => $key) ); eval("?>".$compiled); } From 37e60df12cdd1f2a5f9bbc386df982a8b6c69fc2 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Mon, 16 Sep 2013 20:14:44 -0400 Subject: [PATCH 12/15] Revert timezone edit --- test/bootstrap.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/bootstrap.php b/test/bootstrap.php index 2399f38..91f654a 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -9,8 +9,6 @@ * file that was distributed with this source code. */ -date_default_timezone_set('UTC'); - require dirname(__FILE__).'/../src/Mustache/Autoloader.php'; Mustache_Autoloader::register(); From d6e1b4505377d5c803fb90eb1e87355262541a6f Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Mon, 16 Sep 2013 20:17:39 -0400 Subject: [PATCH 13/15] Add copyright/license header --- src/Mustache/Cache.php | 9 +++++++++ src/Mustache/Cache/AbstractCache.php | 9 +++++++++ src/Mustache/Cache/FilesystemCache.php | 9 +++++++++ src/Mustache/Cache/NoopCache.php | 9 +++++++++ test/Mustache/Test/Cache/FilesystemCacheTest.php | 9 +++++++++ 5 files changed, 45 insertions(+) diff --git a/src/Mustache/Cache.php b/src/Mustache/Cache.php index 4797cdf..1561efc 100644 --- a/src/Mustache/Cache.php +++ b/src/Mustache/Cache.php @@ -1,5 +1,14 @@ Date: Mon, 16 Sep 2013 20:50:47 -0400 Subject: [PATCH 14/15] Docs --- src/Mustache/Cache.php | 20 ++++++++++ src/Mustache/Cache/AbstractCache.php | 7 ++++ src/Mustache/Cache/FilesystemCache.php | 53 ++++++++++++++++++++++++++ src/Mustache/Cache/NoopCache.php | 19 +++++++++ 4 files changed, 99 insertions(+) diff --git a/src/Mustache/Cache.php b/src/Mustache/Cache.php index 1561efc..1ca7438 100644 --- a/src/Mustache/Cache.php +++ b/src/Mustache/Cache.php @@ -9,8 +9,28 @@ * file that was distributed with this source code. */ +/** + * Mustache Cache interface. + * + * Interface for caching and loading Mustache_Template classes + * generated by the Mustache_Compiler. + */ interface Mustache_Cache { + /** + * Load a compiled Mustache_Template class from cache. + * + * @param string $key + * @return boolean indicates successfully class load + */ public function load($key); + + /** + * Cache and load a compiled Mustache_Template class. + * + * @param string $key + * @param string $value + * @return void + */ public function cache($key, $value); } diff --git a/src/Mustache/Cache/AbstractCache.php b/src/Mustache/Cache/AbstractCache.php index dc67387..4a5ab90 100644 --- a/src/Mustache/Cache/AbstractCache.php +++ b/src/Mustache/Cache/AbstractCache.php @@ -9,6 +9,13 @@ * file that was distributed with this source code. */ +/** + * Abstract Mustache Cache class. + * + * Provides logging support to child implementations. + * + * @abstract + */ abstract class Mustache_Cache_AbstractCache implements Mustache_Cache { private $logger = null; diff --git a/src/Mustache/Cache/FilesystemCache.php b/src/Mustache/Cache/FilesystemCache.php index 8b100ef..ade547d 100644 --- a/src/Mustache/Cache/FilesystemCache.php +++ b/src/Mustache/Cache/FilesystemCache.php @@ -9,17 +9,39 @@ * file that was distributed with this source code. */ +/** + * Mustache Cache filesystem implementation. + * + * A FilesystemCache instance caches Mustache Template classes from the filesystem by name: + * + * $cache = new Mustache_Cache_FilesystemCache(dirname(__FILE__).'/cache'); + * $cache->cache($className, $compiledSource); + * + * Benefits from any opcode caching that may be setup in your environment. + */ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache { private $baseDir; private $fileMode; + /** + * Filesystem cache constructor. + * + * @param string $baseDir Directory for compiled templates. + * @param int $fileMode Override default permissions for cache files. Defaults to using the system-defined umask. + */ public function __construct($baseDir, $fileMode = null) { $this->baseDir = $baseDir; $this->fileMode = $fileMode; } + /** + * Load the class from cache using `require_once`. + * + * @param string $key + * @return boolean + */ public function load($key) { $fileName = $this->getCacheFilename($key); @@ -32,6 +54,13 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache return true; } + /** + * Cache and load the compiled class + * + * @param string $key + * @param string $value + * @return void + */ public function cache($key, $value) { $fileName = $this->getCacheFilename($key); @@ -46,11 +75,26 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache $this->load($key); } + /** + * Build the cache filename. + * Subclasses should override for custom cache directory structures. + * + * @param string $name + * @return string + */ protected function getCacheFilename($name) { return sprintf('%s/%s.php', $this->baseDir, $name); } + /** + * Create cache directory + * + * @param string $fileName + * @return string + * + * @throws Mustache_Exception_RuntimeException If unable to create directory + */ private function buildDirectoryForFilename($fileName) { $dirName = dirname($fileName); @@ -69,6 +113,15 @@ class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache return $dirName; } + /** + * Write cache file + * + * @param string $fileName + * @param string $value + * @return void + * + * @throws Mustache_Exception_RuntimeException If unable to write file + */ private function writeFile($fileName, $value) { $dirName = $this->buildDirectoryForFilename($fileName); diff --git a/src/Mustache/Cache/NoopCache.php b/src/Mustache/Cache/NoopCache.php index df3fbf0..bd54362 100644 --- a/src/Mustache/Cache/NoopCache.php +++ b/src/Mustache/Cache/NoopCache.php @@ -9,13 +9,32 @@ * file that was distributed with this source code. */ +/** + * Mustache Cache in-memory implementation. + * + * In-memory implementation useful during development. + * Not recommended for production use. + */ class Mustache_Cache_NoopCache extends Mustache_Cache_AbstractCache { + /** + * Loads nothing. Move along. + * + * @param string $key + * @return boolean + */ public function load($key) { return false; } + /** + * Loads the compiled Mustache Template class without caching. + * + * @param string $key + * @param string $compiled + * @return void + */ public function cache($key, $compiled) { $this->log( From e07c9422902d895e51107254f6cc738f1cf923f8 Mon Sep 17 00:00:00 2001 From: Amit Snyderman Date: Tue, 17 Sep 2013 14:24:28 -0400 Subject: [PATCH 15/15] Fix docblock --- src/Mustache/Engine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mustache/Engine.php b/src/Mustache/Engine.php index f66594f..488dd84 100644 --- a/src/Mustache/Engine.php +++ b/src/Mustache/Engine.php @@ -487,7 +487,7 @@ class Mustache_Engine } /** - * Set the Mustache Tokenizer instance. + * Set the Mustache Cache instance. * * @param Mustache_Cache $cache */