[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. * 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 * @param array $parameters An array of parameters to pass to the template
* *
* @return string The evaluated template as a string * @return string The evaluated template as a string
@ -77,35 +83,23 @@ class Engine
*/ */
public function render($name, array $parameters = array()) public function render($name, array $parameters = array())
{ {
// split renderer & template list($name, $options) = $this->splitTemplateName($name);
if (false !== $pos = strpos($name, ':'))
{
$renderer = substr($name, 0, $pos);
$name = substr($name, $pos + 1);
}
else
{
$renderer = 'php';
}
// load // load
$template = $this->loader->load($name, $renderer); $template = $this->loader->load($name, $options);
if (false === $template) 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->current = $name;
$this->parents[$name] = null; $this->parents[$name] = null;
// renderer // renderer
if ($template->getRenderer()) $renderer = $template->getRenderer() ? $template->getRenderer() : $options['renderer'];
{
$renderer = $template->getRenderer();
}
if (!isset($this->renderers[$renderer])) if (!isset($this->renderers[$options['renderer']]))
{ {
throw new \InvalidArgumentException(sprintf('The renderer "%s" is not registered.', $renderer)); throw new \InvalidArgumentException(sprintf('The renderer "%s" is not registered.', $renderer));
} }
@ -312,4 +306,19 @@ class Engine
{ {
return $this->charset; 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->loader = $loader;
$this->dir = $dir; $this->dir = $dir;
parent::__construct();
} }
/** /**
* Loads a template. * Loads a template.
* *
* @param string $template The logical template name * @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 * @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) if ($this->loader instanceof CompilableLoaderInterface)
{ {
$renderer = 'php'; $options['renderer'] = 'php';
} }
if (file_exists($path)) if (file_exists($path))
@ -66,10 +70,10 @@ class CacheLoader extends Loader
$this->debugger->log(sprintf('Fetching template "%s" from cache', $template)); $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; return false;
} }
@ -86,6 +90,6 @@ class CacheLoader extends Loader
$this->debugger->log(sprintf('Storing template "%s" in cache', $template)); $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); $this->addLoader($loader);
} }
parent::__construct();
} }
/** /**
@ -52,15 +54,15 @@ class ChainLoader extends Loader
* Loads a template. * Loads a template.
* *
* @param string $template The logical template name * @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 * @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) foreach ($this->loaders as $loader)
{ {
if (false !== $ret = $loader->load($template, $renderer)) if (false !== $ret = $loader->load($template, $options))
{ {
return $ret; return $ret;
} }

View File

@ -38,30 +38,41 @@ class FilesystemLoader extends Loader
} }
$this->templatePathPatterns = $templatePathPatterns; $this->templatePathPatterns = $templatePathPatterns;
parent::__construct();
} }
/** /**
* Loads a template. * Loads a template.
* *
* @param string $template The logical template name * @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 * @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)) if (self::isAbsolutePath($template) && file_exists($template))
{ {
return new FileStorage($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) 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) 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); return new FileStorage($file);
@ -69,7 +80,7 @@ class FilesystemLoader extends Loader
if ($this->debugger) 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 abstract class Loader implements LoaderInterface
{ {
protected $debugger; protected $debugger;
protected $defaultOptions;
public function __construct()
{
$this->defaultOptions = array('renderer' => 'php');
}
/** /**
* Sets the debugger to use for this loader. * Sets the debugger to use for this loader.
@ -33,4 +39,27 @@ abstract class Loader implements LoaderInterface
{ {
$this->debugger = $debugger; $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. * Loads a template.
* *
* @param string $template The logical template name * @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 * @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; $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; return false;
@ -202,7 +202,7 @@ $t->is($engine->render('foo', array('foo' => 'foo', 'bar' => 'bar')), 'bar-foo-'
class CompilableTemplateLoader extends Loader implements CompilableLoaderInterface class CompilableTemplateLoader extends Loader implements CompilableLoaderInterface
{ {
public function load($template, $renderer = 'php') public function load($template, array $options = array())
{ {
return new StringStorage($template, 'foo'); return new StringStorage($template, 'foo');
} }

View File

@ -44,7 +44,7 @@ class ProjectTemplateLoaderVar extends Loader
return 'Hello {{ name }}'; 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')) if (method_exists($this, $method = 'get'.ucfirst($template).'Template'))
{ {
@ -89,10 +89,10 @@ mkdir($dir, 0777, true);
$loader = new ProjectTemplateLoader(new CompilableTemplateLoader(), $dir); $loader = new ProjectTemplateLoader(new CompilableTemplateLoader(), $dir);
$loader->setDebugger($debugger = new ProjectTemplateDebugger()); $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->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'); $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->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'); $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()'); $t->diag('->load()');
$loader = new ProjectTemplateLoader(array($loader1, $loader2)); $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('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'); $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 = new ProjectTemplateLoader($pathPattern);
$loader->setDebugger($debugger = new ProjectTemplateDebugger()); $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'); $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)); $loader = new ProjectTemplateLoader(array($fixturesPath.'/null/%name%', $pathPattern));

View File

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