84 lines
2.4 KiB
PHP
84 lines
2.4 KiB
PHP
<?php
|
|
namespace Sasae\Loader;
|
|
|
|
use InvalidArgumentException;
|
|
use Twig\Source;
|
|
use Twig\Error\LoaderError;
|
|
use Twig\Loader\LoaderInterface;
|
|
|
|
/**
|
|
* Provides a simpler Filesystem loader with mechanisms like namespaces omitted.
|
|
*/
|
|
class SasaeFilesystemLoader implements LoaderInterface {
|
|
private string $root;
|
|
|
|
/**
|
|
* @param string $path Base path to the templates directory.
|
|
*/
|
|
public function __construct(string $path) {
|
|
$path = realpath($path);
|
|
if($path === false)
|
|
throw new InvalidArgumentException('$path does not exist.');
|
|
$this->root = $path;
|
|
}
|
|
|
|
/**
|
|
* Returns the underlying path.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPath(): string {
|
|
return $this->root;
|
|
}
|
|
|
|
/** @var array<string, string> */
|
|
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) !== '';
|
|
}
|
|
}
|