Filesystem.php 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. /*
  3. * This file is part of Twig.
  4. *
  5. * (c) 2009 Fabien Potencier
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * Loads template from the filesystem.
  12. *
  13. * @package twig
  14. * @author Fabien Potencier <fabien@symfony.com>
  15. */
  16. class Twig_Loader_Filesystem implements Twig_LoaderInterface
  17. {
  18. protected $paths;
  19. protected $cache;
  20. /**
  21. * Constructor.
  22. *
  23. * @param string|array $paths A path or an array of paths where to look for templates
  24. */
  25. public function __construct($paths)
  26. {
  27. $this->setPaths($paths);
  28. }
  29. /**
  30. * Returns the paths to the templates.
  31. *
  32. * @return array The array of paths where to look for templates
  33. */
  34. public function getPaths()
  35. {
  36. return $this->paths;
  37. }
  38. /**
  39. * Sets the paths where templates are stored.
  40. *
  41. * @param string|array $paths A path or an array of paths where to look for templates
  42. */
  43. public function setPaths($paths)
  44. {
  45. if (!is_array($paths)) {
  46. $paths = array($paths);
  47. }
  48. $this->paths = array();
  49. foreach ($paths as $path) {
  50. $this->addPath($path);
  51. }
  52. }
  53. /**
  54. * Adds a path where templates are stored.
  55. *
  56. * @param string $path A path where to look for templates
  57. */
  58. public function addPath($path)
  59. {
  60. // invalidate the cache
  61. $this->cache = array();
  62. if (!is_dir($path)) {
  63. throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
  64. }
  65. $this->paths[] = $path;
  66. }
  67. /**
  68. * Gets the source code of a template, given its name.
  69. *
  70. * @param string $name The name of the template to load
  71. *
  72. * @return string The template source code
  73. */
  74. public function getSource($name)
  75. {
  76. return file_get_contents($this->findTemplate($name));
  77. }
  78. /**
  79. * Gets the cache key to use for the cache for a given template name.
  80. *
  81. * @param string $name The name of the template to load
  82. *
  83. * @return string The cache key
  84. */
  85. public function getCacheKey($name)
  86. {
  87. return $this->findTemplate($name);
  88. }
  89. /**
  90. * Returns true if the template is still fresh.
  91. *
  92. * @param string $name The template name
  93. * @param timestamp $time The last modification time of the cached template
  94. */
  95. public function isFresh($name, $time)
  96. {
  97. return filemtime($this->findTemplate($name)) < $time;
  98. }
  99. protected function findTemplate($name)
  100. {
  101. // normalize name
  102. $name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
  103. if (isset($this->cache[$name])) {
  104. return $this->cache[$name];
  105. }
  106. $this->validateName($name);
  107. foreach ($this->paths as $path) {
  108. if (is_file($path.'/'.$name)) {
  109. return $this->cache[$name] = $path.'/'.$name;
  110. }
  111. }
  112. throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths)));
  113. }
  114. protected function validateName($name)
  115. {
  116. if (false !== strpos($name, "\0")) {
  117. throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
  118. }
  119. $parts = explode('/', $name);
  120. $level = 0;
  121. foreach ($parts as $part) {
  122. if ('..' === $part) {
  123. --$level;
  124. } elseif ('.' !== $part) {
  125. ++$level;
  126. }
  127. if ($level < 0) {
  128. throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
  129. }
  130. }
  131. }
  132. }