1<?php 2 3/* 4 * This file is part of Mustache.php. 5 * 6 * (c) 2010-2017 Justin Hileman 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12/** 13 * Mustache Cache filesystem implementation. 14 * 15 * A FilesystemCache instance caches Mustache Template classes from the filesystem by name: 16 * 17 * $cache = new Mustache_Cache_FilesystemCache(dirname(__FILE__).'/cache'); 18 * $cache->cache($className, $compiledSource); 19 * 20 * The FilesystemCache benefits from any opcode caching that may be setup in your environment. So do that, k? 21 */ 22class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache 23{ 24 private $baseDir; 25 private $fileMode; 26 27 /** 28 * Filesystem cache constructor. 29 * 30 * @param string $baseDir Directory for compiled templates 31 * @param int $fileMode Override default permissions for cache files. Defaults to using the system-defined umask 32 */ 33 public function __construct($baseDir, $fileMode = null) 34 { 35 $this->baseDir = $baseDir; 36 $this->fileMode = $fileMode; 37 } 38 39 /** 40 * Load the class from cache using `require_once`. 41 * 42 * @param string $key 43 * 44 * @return bool 45 */ 46 public function load($key) 47 { 48 $fileName = $this->getCacheFilename($key); 49 if (!is_file($fileName)) { 50 return false; 51 } 52 53 require_once $fileName; 54 55 return true; 56 } 57 58 /** 59 * Cache and load the compiled class. 60 * 61 * @param string $key 62 * @param string $value 63 */ 64 public function cache($key, $value) 65 { 66 $fileName = $this->getCacheFilename($key); 67 68 $this->log( 69 Mustache_Logger::DEBUG, 70 'Writing to template cache: "{fileName}"', 71 array('fileName' => $fileName) 72 ); 73 74 $this->writeFile($fileName, $value); 75 $this->load($key); 76 } 77 78 /** 79 * Build the cache filename. 80 * Subclasses should override for custom cache directory structures. 81 * 82 * @param string $name 83 * 84 * @return string 85 */ 86 protected function getCacheFilename($name) 87 { 88 return sprintf('%s/%s.php', $this->baseDir, $name); 89 } 90 91 /** 92 * Create cache directory. 93 * 94 * @throws Mustache_Exception_RuntimeException If unable to create directory 95 * 96 * @param string $fileName 97 * 98 * @return string 99 */ 100 private function buildDirectoryForFilename($fileName) 101 { 102 $dirName = dirname($fileName); 103 if (!is_dir($dirName)) { 104 $this->log( 105 Mustache_Logger::INFO, 106 'Creating Mustache template cache directory: "{dirName}"', 107 array('dirName' => $dirName) 108 ); 109 110 @mkdir($dirName, 0777, true); 111 // @codeCoverageIgnoreStart 112 if (!is_dir($dirName)) { 113 throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName)); 114 } 115 // @codeCoverageIgnoreEnd 116 } 117 118 return $dirName; 119 } 120 121 /** 122 * Write cache file. 123 * 124 * @throws Mustache_Exception_RuntimeException If unable to write file 125 * 126 * @param string $fileName 127 * @param string $value 128 */ 129 private function writeFile($fileName, $value) 130 { 131 $dirName = $this->buildDirectoryForFilename($fileName); 132 133 $this->log( 134 Mustache_Logger::DEBUG, 135 'Caching compiled template to "{fileName}"', 136 array('fileName' => $fileName) 137 ); 138 139 $tempFile = tempnam($dirName, basename($fileName)); 140 if (false !== @file_put_contents($tempFile, $value)) { 141 if (@rename($tempFile, $fileName)) { 142 $mode = isset($this->fileMode) ? $this->fileMode : (0666 & ~umask()); 143 @chmod($fileName, $mode); 144 145 return; 146 } 147 148 // @codeCoverageIgnoreStart 149 $this->log( 150 Mustache_Logger::ERROR, 151 'Unable to rename Mustache temp cache file: "{tempName}" -> "{fileName}"', 152 array('tempName' => $tempFile, 'fileName' => $fileName) 153 ); 154 // @codeCoverageIgnoreEnd 155 } 156 157 // @codeCoverageIgnoreStart 158 throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName)); 159 // @codeCoverageIgnoreEnd 160 } 161} 162