Open
Description
Hello,
I really like the new Theme functionality.
But i was wondering if it would be interesting to move to a Loader concept similar to Twig and incorporate both the folder and theme functionality in it. This would mean that all the template resolve would be incapsulated in one place.
I was thinking something in the like of the code below.
If this is interesting i would be happy to make a complete PR
FilesystemResolveTemplatePath {
/**
* Hint path delimiter value.
*
* @var string
*/
public const HINT_PATH_DELIMITER = '::';
/**
* Identifier of the main namespace.
*
* @var string
*/
public const MAIN_NAMESPACE = '__main__';
/**
* The array of active view paths.
*
* @var array
*/
protected $paths = [];
/**
* Get the fully qualified location of the view.
*
* @param string $name
* @return string
*/
public function find($name)
{
list($namespace, $view) = $this->parseName($name);
return $this->findNamespacedView($view, $namespace);
}
/**
* Adds a path where templates are stored.
*
* @param string $path A path where to look for templates
* @param string $namespace A path namespace
*
* @return void
*/
public function addPath($path, $namespace = self::MAIN_NAMESPACE)
{
$this->paths[$namespace][] = rtrim($path, '/\\');
}
/**
* Prepends a path where templates are stored.
*
* @param string $path A path where to look for templates
* @param string $namespace A path namespace
* @return void
*/
public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
{
$path = rtrim($path, '/\\');
if (!isset($this->paths[$namespace])) {
$this->paths[$namespace][] = $path;
} else {
array_unshift($this->paths[$namespace], $path);
}
}
/**
* @param $name
* @param string $namespace
* @return array
*/
public function parseName($name, $namespace = self::MAIN_NAMESPACE)
{
if ($this->hasNamespaceInformation($name = trim($name))) {
return $this->parseNamespacedName($name);
}
return [$namespace, $name];
}
/**
* Get the segments of a template with a named path.
*
* @param string $name
* @return array
*
* @throws \InvalidArgumentException
*/
protected function parseNamespacedName($name)
{
$segments = explode(static::HINT_PATH_DELIMITER, $name);
if (count($segments) != 2) {
throw new InvalidArgumentException("View [$name] has an invalid name.");
}
if (!isset($this->paths[$segments[0]]) || count($this->paths[$segments[0]]) < 1) {
throw new InvalidArgumentException("No path defined for namespace [{$segments[0]}].");
}
return $segments;
}
/**
* Get the path to a template with a named path.
*
* @param string $name
* @param $namespace
* @return string
*/
protected function findNamespacedView($name, $namespace)
{
return $this->findInPaths($name, $this->paths[$namespace]);
}
/**
* Find the given view in the list of paths.
*
* @param string $name
* @param array $paths
* @return string
*
* @throws \InvalidArgumentException
*/
protected function findInPaths($name, $paths)
{
foreach ((array)$paths as $path) {
$file = $this->getViewFilename($name);
if (file_exists($viewPath = $path . '/' . $file)) {
return $viewPath;
}
}
throw new TemplateNotFound(
$name,
$paths,
'View [' . $name . '] not found in paths [' . implode(', ', $paths) . '].'
);
}
/**
* Returns whether or not the view name has any hint information.
*
* @param string $name
* @return bool
*/
public function hasNamespaceInformation($name)
{
return strpos($name, static::HINT_PATH_DELIMITER) > 0;
}
}
Metadata
Metadata
Assignees
Labels
No labels