root = $path; } /** * Returns the underlying path. * * @return string */ public function getPath(): string { return $this->root; } /** @var array */ private array $absPaths = []; private function getAbsolutePath(string $path, bool $throw): string { $cachePath = $path; if(array_key_exists($cachePath, $this->absPaths)) return $this->absPaths[$cachePath]; if(pathinfo($path, PATHINFO_EXTENSION) === '') $path = rtrim($path, '.') . '.twig'; $absPath = realpath($this->root . DIRECTORY_SEPARATOR . $path); if($absPath === false) { if(!$throw) return ''; throw new LoaderError(sprintf('Could not find template "%s" in "%s".', $path, $this->root)); } if(!str_starts_with($absPath, $this->root)) { if(!$throw) return ''; throw new LoaderError(sprintf('Attempting to load "%s" which is outside of the template directory.', $absPath)); } return $this->absPaths[$cachePath] = $absPath; } public function getSourceContext(string $name): Source { $path = $this->getAbsolutePath($name, true); $body = file_get_contents($path); if($body === false) throw new LoaderError(sprintf('Was unable to read "%s"', $path)); return new Source($body, $name, $path); } public function getCacheKey(string $name): string { return $this->getAbsolutePath($name, true); } public function isFresh(string $name, int $time): bool { return filemtime($this->getAbsolutePath($name, true)) < $time; } public function exists(string $name) { return $this->getAbsolutePath($name, false) !== ''; } }