Просмотр файла engine/classes/lib/Twig/Loader/Filesystem.php

Размер файла: 5.83Kb
  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.  
  25. /**
  26. * Constructor.
  27. *
  28. * @param string|array $paths A path or an array of paths where to look for templates
  29. */
  30. public function __construct($paths = array())
  31. {
  32. if ($paths) {
  33. $this->setPaths($paths);
  34. }
  35. }
  36.  
  37. /**
  38. * Returns the paths to the templates.
  39. *
  40. * @param string $namespace A path namespace
  41. *
  42. * @return array The array of paths where to look for templates
  43. */
  44. public function getPaths($namespace = self::MAIN_NAMESPACE)
  45. {
  46. return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
  47. }
  48.  
  49. /**
  50. * Returns the path namespaces.
  51. *
  52. * The main namespace is always defined.
  53. *
  54. * @return array The array of defined namespaces
  55. */
  56. public function getNamespaces()
  57. {
  58. return array_keys($this->paths);
  59. }
  60.  
  61. /**
  62. * Sets the paths where templates are stored.
  63. *
  64. * @param string|array $paths A path or an array of paths where to look for templates
  65. * @param string $namespace A path namespace
  66. */
  67. public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
  68. {
  69. if (!is_array($paths)) {
  70. $paths = array($paths);
  71. }
  72.  
  73. $this->paths[$namespace] = array();
  74. foreach ($paths as $path) {
  75. $this->addPath($path, $namespace);
  76. }
  77. }
  78.  
  79. /**
  80. * Adds a path where templates are stored.
  81. *
  82. * @param string $path A path where to look for templates
  83. * @param string $namespace A path name
  84. *
  85. * @throws Twig_Error_Loader
  86. */
  87. public function addPath($path, $namespace = self::MAIN_NAMESPACE)
  88. {
  89. // invalidate the cache
  90. $this->cache = array();
  91.  
  92. if (!is_dir($path)) {
  93. throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
  94. }
  95.  
  96. $this->paths[$namespace][] = rtrim($path, '/\\');
  97. }
  98.  
  99. /**
  100. * Prepends a path where templates are stored.
  101. *
  102. * @param string $path A path where to look for templates
  103. * @param string $namespace A path name
  104. *
  105. * @throws Twig_Error_Loader
  106. */
  107. public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
  108. {
  109. // invalidate the cache
  110. $this->cache = array();
  111.  
  112. if (!is_dir($path)) {
  113. throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
  114. }
  115.  
  116. $path = rtrim($path, '/\\');
  117.  
  118. if (!isset($this->paths[$namespace])) {
  119. $this->paths[$namespace][] = $path;
  120. } else {
  121. array_unshift($this->paths[$namespace], $path);
  122. }
  123. }
  124.  
  125. /**
  126. * {@inheritdoc}
  127. */
  128. public function getSource($name)
  129. {
  130. return file_get_contents($this->findTemplate($name));
  131. }
  132.  
  133. /**
  134. * {@inheritdoc}
  135. */
  136. public function getCacheKey($name)
  137. {
  138. return $this->findTemplate($name);
  139. }
  140.  
  141. /**
  142. * {@inheritdoc}
  143. */
  144. public function exists($name)
  145. {
  146. $name = (string) $name;
  147. if (isset($this->cache[$name])) {
  148. return true;
  149. }
  150.  
  151. try {
  152. $this->findTemplate($name);
  153.  
  154. return true;
  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. $name = (string) $name;
  171.  
  172. // normalize name
  173. $name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
  174.  
  175. if (isset($this->cache[$name])) {
  176. return $this->cache[$name];
  177. }
  178.  
  179. $this->validateName($name);
  180.  
  181. $namespace = self::MAIN_NAMESPACE;
  182. $shortname = $name;
  183. if (isset($name[0]) && '@' == $name[0]) {
  184. if (false === $pos = strpos($name, '/')) {
  185. throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
  186. }
  187.  
  188. $namespace = substr($name, 1, $pos - 1);
  189. $shortname = substr($name, $pos + 1);
  190. }
  191.  
  192. if (!isset($this->paths[$namespace])) {
  193. throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
  194. }
  195.  
  196. foreach ($this->paths[$namespace] as $path) {
  197. if (is_file($path.'/'.$shortname)) {
  198. return $this->cache[$name] = $path.'/'.$shortname;
  199. }
  200. }
  201.  
  202. throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
  203. }
  204.  
  205. protected function validateName($name)
  206. {
  207. if (false !== strpos($name, "\0")) {
  208. throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
  209. }
  210.  
  211. $name = ltrim($name, '/');
  212. $parts = explode('/', $name);
  213. $level = 0;
  214. foreach ($parts as $part) {
  215. if ('..' === $part) {
  216. --$level;
  217. } elseif ('.' !== $part) {
  218. ++$level;
  219. }
  220.  
  221. if ($level < 0) {
  222. throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
  223. }
  224. }
  225. }
  226. }