[Templating] changed the load() signature for loaders to allow for more flexibility

This commit is contained in:
Fabien Potencier 2010-01-28 07:56:34 +01:00
parent 869a4698ed
commit 5c20bfec92
11 changed files with 100 additions and 45 deletions

View File

@ -67,7 +67,13 @@ class Engine
/**
* Renders a template.
*
* @param string $name A template logical name
* The template name is composed of segments separated by a colon (:).
* By default, this engine knows how to parse templates with one or two segments:
*
* * index: The template logical name is index and the renderer is php
* * index:twig: The template logical name is index and the renderer is twig
*
* @param string $name A template name
* @param array $parameters An array of parameters to pass to the template
*
* @return string The evaluated template as a string
@ -77,35 +83,23 @@ class Engine
*/
public function render($name, array $parameters = array())
{
// split renderer & template
if (false !== $pos = strpos($name, ':'))
{
$renderer = substr($name, 0, $pos);
$name = substr($name, $pos + 1);
}
else
{
$renderer = 'php';
}
list($name, $options) = $this->splitTemplateName($name);
// load
$template = $this->loader->load($name, $renderer);
$template = $this->loader->load($name, $options);
if (false === $template)
{
throw new \InvalidArgumentException(sprintf('The template "%s" does not exist (renderer: %s).', $name, $renderer));
throw new \InvalidArgumentException(sprintf('The template "%s" does not exist (renderer: %s).', $name, $options['renderer']));
}
$this->current = $name;
$this->parents[$name] = null;
// renderer
if ($template->getRenderer())
{
$renderer = $template->getRenderer();
}
$renderer = $template->getRenderer() ? $template->getRenderer() : $options['renderer'];
if (!isset($this->renderers[$renderer]))
if (!isset($this->renderers[$options['renderer']]))
{
throw new \InvalidArgumentException(sprintf('The renderer "%s" is not registered.', $renderer));
}
@ -312,4 +306,19 @@ class Engine
{
return $this->charset;
}
protected function splitTemplateName($name)
{
if (false !== $pos = strpos($name, ':'))
{
$renderer = substr($name, $pos + 1);
$name = substr($name, 0, $pos);
}
else
{
$renderer = 'php';
}
return array($name, array('renderer' => $renderer));
}
}

View File

@ -40,23 +40,27 @@ class CacheLoader extends Loader
{
$this->loader = $loader;
$this->dir = $dir;
parent::__construct();
}
/**
* Loads a template.
*
* @param string $template The logical template name
* @param string $renderer The renderer to use
* @param array $options An array of options
*
* @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
*/
public function load($template, $renderer = 'php')
public function load($template, array $options = array())
{
$path = $this->dir.DIRECTORY_SEPARATOR.md5($template.$renderer).'.tpl';
$options = $this->mergeDefaultOptions($options);
$path = $this->dir.DIRECTORY_SEPARATOR.md5($template.$options['renderer']).'.tpl';
if ($this->loader instanceof CompilableLoaderInterface)
{
$renderer = 'php';
$options['renderer'] = 'php';
}
if (file_exists($path))
@ -66,10 +70,10 @@ class CacheLoader extends Loader
$this->debugger->log(sprintf('Fetching template "%s" from cache', $template));
}
return new FileStorage($path, $renderer);
return new FileStorage($path, $options['renderer']);
}
if (false === $content = $this->loader->load($template, $renderer))
if (false === $content = $this->loader->load($template, $options))
{
return false;
}
@ -86,6 +90,6 @@ class CacheLoader extends Loader
$this->debugger->log(sprintf('Storing template "%s" in cache', $template));
}
return new FileStorage($path, $renderer);
return new FileStorage($path, $options['renderer']);
}
}

View File

@ -36,6 +36,8 @@ class ChainLoader extends Loader
{
$this->addLoader($loader);
}
parent::__construct();
}
/**
@ -52,15 +54,15 @@ class ChainLoader extends Loader
* Loads a template.
*
* @param string $template The logical template name
* @param string $renderer The renderer to use
* @param array $options An array of options
*
* @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
*/
public function load($template, $renderer = 'php')
public function load($template, array $options = array())
{
foreach ($this->loaders as $loader)
{
if (false !== $ret = $loader->load($template, $renderer))
if (false !== $ret = $loader->load($template, $options))
{
return $ret;
}

View File

@ -38,30 +38,41 @@ class FilesystemLoader extends Loader
}
$this->templatePathPatterns = $templatePathPatterns;
parent::__construct();
}
/**
* Loads a template.
*
* @param string $template The logical template name
* @param string $renderer The renderer to use
* @param array $options An array of options
*
* @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
*/
public function load($template, $renderer = 'php')
public function load($template, array $options = array())
{
if (self::isAbsolutePath($template) && file_exists($template))
{
return new FileStorage($template);
}
$options = $this->mergeDefaultOptions($options);
$options['name'] = $template;
$replacements = array();
foreach ($options as $key => $value)
{
$replacements['%'.$key.'%'] = $value;
}
foreach ($this->templatePathPatterns as $templatePathPattern)
{
if (is_file($file = strtr($templatePathPattern, array('%name%' => $template, '%renderer%' => $renderer))))
if (is_file($file = strtr($templatePathPattern, $replacements)))
{
if ($this->debugger)
{
$this->debugger->log(sprintf('Loaded template file "%s" (renderer: %s)', $file, $renderer));
$this->debugger->log(sprintf('Loaded template file "%s" (renderer: %s)', $file, $options['renderer']));
}
return new FileStorage($file);
@ -69,7 +80,7 @@ class FilesystemLoader extends Loader
if ($this->debugger)
{
$this->debugger->log(sprintf('Failed loading template file "%s" (renderer: %s)', $file, $renderer));
$this->debugger->log(sprintf('Failed loading template file "%s" (renderer: %s)', $file, $options['renderer']));
}
}

View File

@ -23,6 +23,12 @@ use Symfony\Components\Templating\DebuggerInterface;
abstract class Loader implements LoaderInterface
{
protected $debugger;
protected $defaultOptions;
public function __construct()
{
$this->defaultOptions = array('renderer' => 'php');
}
/**
* Sets the debugger to use for this loader.
@ -33,4 +39,27 @@ abstract class Loader implements LoaderInterface
{
$this->debugger = $debugger;
}
/**
* Sets a default option.
*
* @param string $name The option name
* @param mixed $value The option value
*/
public function setDefaultOption($name, $value)
{
$this->defaultOptions[$name] = $value;
}
/**
* Merges the default options with the given set of options.
*
* @param array $options An array of options
*
* @return array The merged set of options
*/
protected function mergeDefaultOptions(array $options)
{
return array_merge($this->defaultOptions, $options);
}
}

View File

@ -24,9 +24,9 @@ interface LoaderInterface
* Loads a template.
*
* @param string $template The logical template name
* @param string $renderer The renderer to use
* @param array $options An array of options
*
* @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
*/
function load($template, $renderer = 'php');
function load($template, array $options = array());
}

View File

@ -54,11 +54,11 @@ class ProjectTemplateLoader extends Loader
$this->templates[$name] = $template;
}
public function load($template, $renderer = 'php')
public function load($template, array $options = array())
{
if (isset($this->templates[$template.'.'.$renderer]))
if (isset($this->templates[$template.'.'.$options['renderer']]))
{
return new StringStorage($this->templates[$template.'.'.$renderer]);
return new StringStorage($this->templates[$template.'.'.$options['renderer']]);
}
return false;
@ -202,7 +202,7 @@ $t->is($engine->render('foo', array('foo' => 'foo', 'bar' => 'bar')), 'bar-foo-'
class CompilableTemplateLoader extends Loader implements CompilableLoaderInterface
{
public function load($template, $renderer = 'php')
public function load($template, array $options = array())
{
return new StringStorage($template, 'foo');
}

View File

@ -44,7 +44,7 @@ class ProjectTemplateLoaderVar extends Loader
return 'Hello {{ name }}';
}
public function load($template, $renderer = 'php')
public function load($template, array $options = array())
{
if (method_exists($this, $method = 'get'.ucfirst($template).'Template'))
{
@ -89,10 +89,10 @@ mkdir($dir, 0777, true);
$loader = new ProjectTemplateLoader(new CompilableTemplateLoader(), $dir);
$loader->setDebugger($debugger = new ProjectTemplateDebugger());
$template = $loader->load('special', 'comp');
$template = $loader->load('special', array('renderer' => 'comp'));
$t->ok($debugger->hasMessage('Storing template'), '->load() logs a "Storing template" message if the template is found');
$t->is($template->getRenderer(), 'php', '->load() changes the renderer to php if the template is compilable');
$template = $loader->load('special', 'comp');
$template = $loader->load('special', array('renderer' => 'comp'));
$t->ok($debugger->hasMessage('Fetching template'), '->load() logs a "Storing template" message if the template is fetched from cache');
$t->is($template->getRenderer(), 'php', '->load() changes the renderer to php if the template is compilable');

View File

@ -47,5 +47,5 @@ $t->is($loader->getLoaders(), array($loader1, $loader2), '->addLoader() adds a t
$t->diag('->load()');
$loader = new ProjectTemplateLoader(array($loader1, $loader2));
$t->ok($loader->load('bar') === false, '->load() returns false if the template is not found');
$t->ok($loader->load('foo', 'xml') === false, '->load() returns false if the template does not exists for the given renderer');
$t->ok($loader->load('foo', array('renderer' => 'xml')) === false, '->load() returns false if the template does not exists for the given renderer');
$t->ok($loader->load('foo') instanceof FileStorage, '->load() returns a FileStorage if the template exists');

View File

@ -64,7 +64,7 @@ $t->is((string) $storage, $path.'/foo.php', '->load() returns a FileStorage poin
$loader = new ProjectTemplateLoader($pathPattern);
$loader->setDebugger($debugger = new ProjectTemplateDebugger());
$t->ok($loader->load('foo', 'xml') === false, '->load() returns false if the template does not exists for the given renderer');
$t->ok($loader->load('foo', array('renderer' => 'xml')) === false, '->load() returns false if the template does not exists for the given renderer');
$t->ok($debugger->hasMessage('Failed loading template'), '->load() logs a "Failed loading template" message if the template is not found');
$loader = new ProjectTemplateLoader(array($fixturesPath.'/null/%name%', $pathPattern));

View File

@ -19,7 +19,7 @@ $t = new LimeTest(1);
class ProjectTemplateLoader extends Loader
{
public function load($template, $renderer = 'php')
public function load($template, array $options = array())
{
}