From 5c20bfec9245c311bb4cd3b734c59b556c771c78 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 28 Jan 2010 07:56:34 +0100 Subject: [PATCH] [Templating] changed the load() signature for loaders to allow for more flexibility --- src/Symfony/Components/Templating/Engine.php | 45 +++++++++++-------- .../Templating/Loader/CacheLoader.php | 18 +++++--- .../Templating/Loader/ChainLoader.php | 8 ++-- .../Templating/Loader/FilesystemLoader.php | 21 ++++++--- .../Components/Templating/Loader/Loader.php | 29 ++++++++++++ .../Templating/Loader/LoaderInterface.php | 4 +- .../Components/Templating/EngineTest.php | 8 ++-- .../Templating/Loader/CacheLoaderTest.php | 6 +-- .../Templating/Loader/ChainLoaderTest.php | 2 +- .../Loader/FilesystemLoaderTest.php | 2 +- .../Templating/Loader/LoaderTest.php | 2 +- 11 files changed, 100 insertions(+), 45 deletions(-) diff --git a/src/Symfony/Components/Templating/Engine.php b/src/Symfony/Components/Templating/Engine.php index 9f3197932d..304f4ffdcb 100644 --- a/src/Symfony/Components/Templating/Engine.php +++ b/src/Symfony/Components/Templating/Engine.php @@ -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)); + } } diff --git a/src/Symfony/Components/Templating/Loader/CacheLoader.php b/src/Symfony/Components/Templating/Loader/CacheLoader.php index f352029ac3..224ba8361a 100644 --- a/src/Symfony/Components/Templating/Loader/CacheLoader.php +++ b/src/Symfony/Components/Templating/Loader/CacheLoader.php @@ -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']); } } diff --git a/src/Symfony/Components/Templating/Loader/ChainLoader.php b/src/Symfony/Components/Templating/Loader/ChainLoader.php index 6ca22315bf..714919217f 100644 --- a/src/Symfony/Components/Templating/Loader/ChainLoader.php +++ b/src/Symfony/Components/Templating/Loader/ChainLoader.php @@ -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; } diff --git a/src/Symfony/Components/Templating/Loader/FilesystemLoader.php b/src/Symfony/Components/Templating/Loader/FilesystemLoader.php index 026b3997ea..cbdb6de558 100644 --- a/src/Symfony/Components/Templating/Loader/FilesystemLoader.php +++ b/src/Symfony/Components/Templating/Loader/FilesystemLoader.php @@ -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'])); } } diff --git a/src/Symfony/Components/Templating/Loader/Loader.php b/src/Symfony/Components/Templating/Loader/Loader.php index 960d092651..4df24149be 100644 --- a/src/Symfony/Components/Templating/Loader/Loader.php +++ b/src/Symfony/Components/Templating/Loader/Loader.php @@ -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); + } } diff --git a/src/Symfony/Components/Templating/Loader/LoaderInterface.php b/src/Symfony/Components/Templating/Loader/LoaderInterface.php index 74fcfa2df5..9dda9a1ec2 100644 --- a/src/Symfony/Components/Templating/Loader/LoaderInterface.php +++ b/src/Symfony/Components/Templating/Loader/LoaderInterface.php @@ -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()); } diff --git a/tests/unit/Symfony/Components/Templating/EngineTest.php b/tests/unit/Symfony/Components/Templating/EngineTest.php index aa734648e4..51fccaa609 100644 --- a/tests/unit/Symfony/Components/Templating/EngineTest.php +++ b/tests/unit/Symfony/Components/Templating/EngineTest.php @@ -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'); } diff --git a/tests/unit/Symfony/Components/Templating/Loader/CacheLoaderTest.php b/tests/unit/Symfony/Components/Templating/Loader/CacheLoaderTest.php index 164134a57b..61982f292a 100644 --- a/tests/unit/Symfony/Components/Templating/Loader/CacheLoaderTest.php +++ b/tests/unit/Symfony/Components/Templating/Loader/CacheLoaderTest.php @@ -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'); diff --git a/tests/unit/Symfony/Components/Templating/Loader/ChainLoaderTest.php b/tests/unit/Symfony/Components/Templating/Loader/ChainLoaderTest.php index 5bd56e098e..882b58a2c4 100644 --- a/tests/unit/Symfony/Components/Templating/Loader/ChainLoaderTest.php +++ b/tests/unit/Symfony/Components/Templating/Loader/ChainLoaderTest.php @@ -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'); diff --git a/tests/unit/Symfony/Components/Templating/Loader/FilesystemLoaderTest.php b/tests/unit/Symfony/Components/Templating/Loader/FilesystemLoaderTest.php index 71612bc1b7..5ae3cdf291 100644 --- a/tests/unit/Symfony/Components/Templating/Loader/FilesystemLoaderTest.php +++ b/tests/unit/Symfony/Components/Templating/Loader/FilesystemLoaderTest.php @@ -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)); diff --git a/tests/unit/Symfony/Components/Templating/Loader/LoaderTest.php b/tests/unit/Symfony/Components/Templating/Loader/LoaderTest.php index 0e2a8ae22c..5031c6296b 100644 --- a/tests/unit/Symfony/Components/Templating/Loader/LoaderTest.php +++ b/tests/unit/Symfony/Components/Templating/Loader/LoaderTest.php @@ -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()) { }