vq2-system_library_template_Twig_Loader_Filesystem.php (7265B)
1 <?php 2 3 /* 4 * This file is part of Twig. 5 * 6 * (c) 2009 Fabien Potencier 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 * Loads template from the filesystem. 14 * 15 * @author Fabien Potencier <fabien@symfony.com> 16 */ 17 class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface 18 { 19 /** Identifier of the main namespace. */ 20 const MAIN_NAMESPACE = '__main__'; 21 22 protected $paths = array(); 23 protected $cache = array(); 24 protected $errorCache = array(); 25 26 /** 27 * Constructor. 28 * 29 * @param string|array $paths A path or an array of paths where to look for templates 30 */ 31 public function __construct($paths = array()) 32 { 33 if ($paths) { 34 $this->setPaths($paths); 35 } 36 } 37 38 /** 39 * Returns the paths to the templates. 40 * 41 * @param string $namespace A path namespace 42 * 43 * @return array The array of paths where to look for templates 44 */ 45 public function getPaths($namespace = self::MAIN_NAMESPACE) 46 { 47 return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array(); 48 } 49 50 /** 51 * Returns the path namespaces. 52 * 53 * The main namespace is always defined. 54 * 55 * @return array The array of defined namespaces 56 */ 57 public function getNamespaces() 58 { 59 return array_keys($this->paths); 60 } 61 62 /** 63 * Sets the paths where templates are stored. 64 * 65 * @param string|array $paths A path or an array of paths where to look for templates 66 * @param string $namespace A path namespace 67 */ 68 public function setPaths($paths, $namespace = self::MAIN_NAMESPACE) 69 { 70 if (!is_array($paths)) { 71 $paths = array($paths); 72 } 73 74 $this->paths[$namespace] = array(); 75 foreach ($paths as $path) { 76 $this->addPath($path, $namespace); 77 } 78 } 79 80 /** 81 * Adds a path where templates are stored. 82 * 83 * @param string $path A path where to look for templates 84 * @param string $namespace A path name 85 * 86 * @throws Twig_Error_Loader 87 */ 88 public function addPath($path, $namespace = self::MAIN_NAMESPACE) 89 { 90 // invalidate the cache 91 $this->cache = $this->errorCache = array(); 92 93 if (!is_dir($path)) { 94 throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); 95 } 96 97 $this->paths[$namespace][] = rtrim($path, '/\\'); 98 } 99 100 /** 101 * Prepends a path where templates are stored. 102 * 103 * @param string $path A path where to look for templates 104 * @param string $namespace A path name 105 * 106 * @throws Twig_Error_Loader 107 */ 108 public function prependPath($path, $namespace = self::MAIN_NAMESPACE) 109 { 110 // invalidate the cache 111 $this->cache = $this->errorCache = array(); 112 113 if (!is_dir($path)) { 114 throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); 115 } 116 117 $path = rtrim($path, '/\\'); 118 119 if (!isset($this->paths[$namespace])) { 120 $this->paths[$namespace][] = $path; 121 } else { 122 array_unshift($this->paths[$namespace], $path); 123 } 124 } 125 126 /** 127 * {@inheritdoc} 128 */ 129 public function getSource($name) 130 { 131 return file_get_contents($this->findTemplate($name)); 132 } 133 134 /** 135 * {@inheritdoc} 136 */ 137 public function getCacheKey($name) 138 { 139 return $this->findTemplate($name); 140 } 141 142 /** 143 * {@inheritdoc} 144 */ 145 public function exists($name) 146 { 147 $name = $this->normalizeName($name); 148 149 if (isset($this->cache[$name])) { 150 return true; 151 } 152 153 try { 154 return false !== $this->findTemplate($name, false); 155 } catch (Twig_Error_Loader $exception) { 156 return false; 157 } 158 } 159 160 /** 161 * {@inheritdoc} 162 */ 163 public function isFresh($name, $time) 164 { 165 return filemtime($this->findTemplate($name)) <= $time; 166 } 167 168 protected function findTemplate($name) 169 { 170 $throw = func_num_args() > 1 ? func_get_arg(1) : true; 171 $name = $this->normalizeName($name); 172 173 if (isset($this->cache[$name])) { 174 return $this->cache[$name]; 175 } 176 177 if (isset($this->errorCache[$name])) { 178 if (!$throw) { 179 return false; 180 } 181 182 throw new Twig_Error_Loader($this->errorCache[$name]); 183 } 184 185 $this->validateName($name); 186 187 list($namespace, $shortname) = $this->parseName($name); 188 189 if (!isset($this->paths[$namespace])) { 190 $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace); 191 192 if (!$throw) { 193 return false; 194 } 195 196 throw new Twig_Error_Loader($this->errorCache[$name]); 197 } 198 199 foreach ($this->paths[$namespace] as $path) { 200 if (is_file($path.'/'.$shortname)) { 201 if (false !== $realpath = realpath($path.'/'.$shortname)) { 202 return $this->cache[$name] = VQMod::modCheck($realpath, DIR_TEMPLATE . $name); 203 } 204 205 return $this->cache[$name] = $path.'/'.$shortname; 206 } 207 } 208 209 $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])); 210 211 if (!$throw) { 212 return false; 213 } 214 215 throw new Twig_Error_Loader($this->errorCache[$name]); 216 } 217 218 protected function parseName($name, $default = self::MAIN_NAMESPACE) 219 { 220 if (isset($name[0]) && '@' == $name[0]) { 221 if (false === $pos = strpos($name, '/')) { 222 throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); 223 } 224 225 $namespace = substr($name, 1, $pos - 1); 226 $shortname = substr($name, $pos + 1); 227 228 return array($namespace, $shortname); 229 } 230 231 return array($default, $name); 232 } 233 234 protected function normalizeName($name) 235 { 236 return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name)); 237 } 238 239 protected function validateName($name) 240 { 241 if (false !== strpos($name, "\0")) { 242 throw new Twig_Error_Loader('A template name cannot contain NUL bytes.'); 243 } 244 245 $name = ltrim($name, '/'); 246 $parts = explode('/', $name); 247 $level = 0; 248 foreach ($parts as $part) { 249 if ('..' === $part) { 250 --$level; 251 } elseif ('.' !== $part) { 252 ++$level; 253 } 254 255 if ($level < 0) { 256 throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); 257 } 258 } 259 } 260 }