PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/twig/twig/lib/Twig/Loader/Filesystem.php

https://gitlab.com/gideonmarked/PLCPortal
PHP | 303 lines | 196 code | 45 blank | 62 comment | 25 complexity | 85136bea69a12c734768978ca8359b6d MD5 | raw file
  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. * @author Fabien Potencier <fabien@symfony.com>
  14. */
  15. class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
  16. {
  17. /** Identifier of the main namespace. */
  18. const MAIN_NAMESPACE = '__main__';
  19. protected $paths = array();
  20. protected $cache = array();
  21. protected $errorCache = array();
  22. private $rootPath;
  23. /**
  24. * @param string|array $paths A path or an array of paths where to look for templates
  25. * @param string|null $rootPath The root path common to all relative paths (null for getcwd())
  26. */
  27. public function __construct($paths = array(), $rootPath = null)
  28. {
  29. $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).DIRECTORY_SEPARATOR;
  30. if (false !== $realPath = realpath($rootPath)) {
  31. $this->rootPath = $realPath.DIRECTORY_SEPARATOR;
  32. }
  33. if ($paths) {
  34. $this->setPaths($paths);
  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. * Returns the path namespaces.
  50. *
  51. * The main namespace is always defined.
  52. *
  53. * @return array The array of defined namespaces
  54. */
  55. public function getNamespaces()
  56. {
  57. return array_keys($this->paths);
  58. }
  59. /**
  60. * Sets the paths where templates are stored.
  61. *
  62. * @param string|array $paths A path or an array of paths where to look for templates
  63. * @param string $namespace A path namespace
  64. */
  65. public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
  66. {
  67. if (!is_array($paths)) {
  68. $paths = array($paths);
  69. }
  70. $this->paths[$namespace] = array();
  71. foreach ($paths as $path) {
  72. $this->addPath($path, $namespace);
  73. }
  74. }
  75. /**
  76. * Adds a path where templates are stored.
  77. *
  78. * @param string $path A path where to look for templates
  79. * @param string $namespace A path namespace
  80. *
  81. * @throws Twig_Error_Loader
  82. */
  83. public function addPath($path, $namespace = self::MAIN_NAMESPACE)
  84. {
  85. // invalidate the cache
  86. $this->cache = $this->errorCache = array();
  87. $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
  88. if (!is_dir($checkPath)) {
  89. throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
  90. }
  91. $this->paths[$namespace][] = rtrim($path, '/\\');
  92. }
  93. /**
  94. * Prepends a path where templates are stored.
  95. *
  96. * @param string $path A path where to look for templates
  97. * @param string $namespace A path namespace
  98. *
  99. * @throws Twig_Error_Loader
  100. */
  101. public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
  102. {
  103. // invalidate the cache
  104. $this->cache = $this->errorCache = array();
  105. $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
  106. if (!is_dir($checkPath)) {
  107. throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
  108. }
  109. $path = rtrim($path, '/\\');
  110. if (!isset($this->paths[$namespace])) {
  111. $this->paths[$namespace][] = $path;
  112. } else {
  113. array_unshift($this->paths[$namespace], $path);
  114. }
  115. }
  116. /**
  117. * {@inheritdoc}
  118. */
  119. public function getSource($name)
  120. {
  121. @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
  122. return file_get_contents($this->findTemplate($name));
  123. }
  124. /**
  125. * {@inheritdoc}
  126. */
  127. public function getSourceContext($name)
  128. {
  129. $path = $this->findTemplate($name);
  130. return new Twig_Source(file_get_contents($path), $name, $path);
  131. }
  132. /**
  133. * {@inheritdoc}
  134. */
  135. public function getCacheKey($name)
  136. {
  137. $path = $this->findTemplate($name);
  138. $len = strlen($this->rootPath);
  139. if (0 === strncmp($this->rootPath, $path, $len)) {
  140. return substr($path, $len);
  141. }
  142. return $path;
  143. }
  144. /**
  145. * {@inheritdoc}
  146. */
  147. public function exists($name)
  148. {
  149. $name = $this->normalizeName($name);
  150. if (isset($this->cache[$name])) {
  151. return true;
  152. }
  153. try {
  154. return false !== $this->findTemplate($name, false);
  155. } catch (Twig_Error_Loader $exception) {
  156. @trigger_error(sprintf('In %s::findTemplate(), you must accept a second argument that when set to "false" returns "false" instead of throwing an exception. Not supporting this argument is deprecated since version 1.27.', get_class($this)), E_USER_DEPRECATED);
  157. return false;
  158. }
  159. }
  160. /**
  161. * {@inheritdoc}
  162. */
  163. public function isFresh($name, $time)
  164. {
  165. return filemtime($this->findTemplate($name)) <= $time;
  166. }
  167. protected function findTemplate($name)
  168. {
  169. $throw = func_num_args() > 1 ? func_get_arg(1) : true;
  170. $name = $this->normalizeName($name);
  171. if (isset($this->cache[$name])) {
  172. return $this->cache[$name];
  173. }
  174. if (isset($this->errorCache[$name])) {
  175. if (!$throw) {
  176. return false;
  177. }
  178. throw new Twig_Error_Loader($this->errorCache[$name]);
  179. }
  180. $this->validateName($name);
  181. list($namespace, $shortname) = $this->parseName($name);
  182. if (!isset($this->paths[$namespace])) {
  183. $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace);
  184. if (!$throw) {
  185. return false;
  186. }
  187. throw new Twig_Error_Loader($this->errorCache[$name]);
  188. }
  189. foreach ($this->paths[$namespace] as $path) {
  190. if (!$this->isAbsolutePath($path)) {
  191. $path = $this->rootPath.'/'.$path;
  192. }
  193. if (is_file($path.'/'.$shortname)) {
  194. if (false !== $realpath = realpath($path.'/'.$shortname)) {
  195. return $this->cache[$name] = $realpath;
  196. }
  197. return $this->cache[$name] = $path.'/'.$shortname;
  198. }
  199. }
  200. $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]));
  201. if (!$throw) {
  202. return false;
  203. }
  204. throw new Twig_Error_Loader($this->errorCache[$name]);
  205. }
  206. protected function parseName($name, $default = self::MAIN_NAMESPACE)
  207. {
  208. if (isset($name[0]) && '@' == $name[0]) {
  209. if (false === $pos = strpos($name, '/')) {
  210. throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
  211. }
  212. $namespace = substr($name, 1, $pos - 1);
  213. $shortname = substr($name, $pos + 1);
  214. return array($namespace, $shortname);
  215. }
  216. return array($default, $name);
  217. }
  218. protected function normalizeName($name)
  219. {
  220. return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name));
  221. }
  222. protected function validateName($name)
  223. {
  224. if (false !== strpos($name, "\0")) {
  225. throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
  226. }
  227. $name = ltrim($name, '/');
  228. $parts = explode('/', $name);
  229. $level = 0;
  230. foreach ($parts as $part) {
  231. if ('..' === $part) {
  232. --$level;
  233. } elseif ('.' !== $part) {
  234. ++$level;
  235. }
  236. if ($level < 0) {
  237. throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
  238. }
  239. }
  240. }
  241. private function isAbsolutePath($file)
  242. {
  243. return strspn($file, '/\\', 0, 1)
  244. || (strlen($file) > 3 && ctype_alpha($file[0])
  245. && substr($file, 1, 1) === ':'
  246. && strspn($file, '/\\', 2, 1)
  247. )
  248. || null !== parse_url($file, PHP_URL_SCHEME)
  249. ;
  250. }
  251. }