Skip to content

Commit

Permalink
removed a circular reference in the definition of the templating and …
Browse files Browse the repository at this point in the history
…Twig services

 * added a new TemplateNameConverter that parses a template name
 * removed the dependency between the Twig loader and the Templating engine
  • Loading branch information
fabpot committed Jan 6, 2011
1 parent d21fb75 commit 911dbe9
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 70 deletions.
Expand Up @@ -21,6 +21,7 @@
<parameter key="templating.helper.form.class">Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper</parameter>
<parameter key="templating.assets.version">null</parameter>
<parameter key="templating.assets.base_urls" type="collection"></parameter>
<parameter key="templating.name_converter.class">Symfony\Bundle\FrameworkBundle\Templating\TemplateNameConverter</parameter>
<parameter key="debug.file_link_format">null</parameter>
</parameters>

Expand Down Expand Up @@ -99,6 +100,10 @@
<argument type="service" id="templating" />
</service>

<service id="templating.name_converter" class="%templating.name_converter.class%">
<argument type="service" id="service_container" />
</service>

<service id="templating.loader" alias="templating.loader.filesystem" />

<service id="templating" alias="templating.engine" />
Expand Down
41 changes: 4 additions & 37 deletions src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php
Expand Up @@ -91,44 +91,11 @@ public function setHelpers(array $helpers)
$this->helpers = $helpers;
}

// parses template names following the following pattern:
// bundle:section:template(.format).renderer
/**
* {@inheritdoc}
*/
public function splitTemplateName($name, array $defaults = array())
{
$parts = explode(':', $name);
if (3 !== count($parts)) {
throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
}

$options = array_replace(
array(
'format' => '',
),
$defaults,
array(
'bundle' => str_replace('\\', '/', $parts[0]),
'controller' => $parts[1],
)
);

$elements = explode('.', $parts[2]);
if (3 === count($elements)) {
$parts[2] = $elements[0];
if ('html' !== $elements[1]) {
$options['format'] = '.'.$elements[1];
}
$options['renderer'] = $elements[2];
} elseif (2 === count($elements)) {
$parts[2] = $elements[0];
$options['renderer'] = $elements[1];
$format = $this->container->get('request')->getRequestFormat();
if (null !== $format && 'html' !== $format) {
$options['format'] = '.'.$format;
}
} else {
throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
}

return array($parts[2], $options);
return $this->container->get('templating.name_converter')->fromShortNotation($name, $defaults);
}
}
@@ -0,0 +1,83 @@
<?php

namespace Symfony\Bundle\FrameworkBundle\Templating;

use Symfony\Component\DependencyInjection\ContainerInterface;

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* TemplateNameConverter converts template name from the short notation
* "bundle:section:template(.format).renderer" to a template name
* and an array of options.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class TemplateNameConverter
{
protected $container;

/**
* Constructor.
*
* @param ContainerInterface $container The DI container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}

/**
* Converts a short template notation to a template name and an array of options.
*
* @param string $name A short template template
* @param array $defaults An array of default options
*
* @return array An array composed of the template name and an array of options
*/
public function fromShortNotation($name, array $defaults = array())
{
$parts = explode(':', $name);
if (3 !== count($parts)) {
throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
}

$options = array_replace(
array(
'format' => '',
),
$defaults,
array(
'bundle' => str_replace('\\', '/', $parts[0]),
'controller' => $parts[1],
)
);

$elements = explode('.', $parts[2]);
if (3 === count($elements)) {
$parts[2] = $elements[0];
if ('html' !== $elements[1]) {
$options['format'] = '.'.$elements[1];
}
$options['renderer'] = $elements[2];
} elseif (2 === count($elements)) {
$parts[2] = $elements[0];
$options['renderer'] = $elements[1];
$format = $this->container->get('request')->getRequestFormat();
if (null !== $format && 'html' !== $format) {
$options['format'] = '.'.$format;
}
} else {
throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name));
}

return array($parts[2], $options);
}
}
Expand Up @@ -12,30 +12,21 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Templating;

use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\Templating\Engine;
use Symfony\Component\Templating\Storage\StringStorage;
use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Renderer\PhpRenderer;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameConverter;

// simulate the rendering of another controller
function foo($engine)
{
return $engine->render('FooBundle:Foo:tpl1.php', array('foo' => 'foo <br />'));
}

class EngineTest extends TestCase
class TemplateNameConverterTest extends TestCase
{
/**
* @dataProvider getSplitTemplateNameTests
* @dataProvider getFromShortNotationTests
*/
public function testSplitTemplateName($name, $parameters)
public function testFromShortNotation($name, $parameters)
{
$engine = new Engine($this->getContainerMock(), $this->getLoaderMock(), array());
$converter = new TemplateNameConverter($this->getContainerMock(), $this->getLoaderMock(), array());

$this->assertEquals($parameters, $engine->splitTemplateName($name));
$this->assertEquals($parameters, $converter->fromShortNotation($name));
}

public function getSplitTemplateNameTests()
public function getFromShortNotationTests()
{
return array(
array('BlogBundle:Post:index.php', array('index', array('bundle' => 'BlogBundle', 'controller' => 'Post', 'renderer' => 'php', 'format' => ''))),
Expand All @@ -45,17 +36,17 @@ public function getSplitTemplateNameTests()
}

/**
* @dataProvider getSplitTemplateNameInvalidTests
* @dataProvider getFromShortNotationInvalidTests
* @expectedException \InvalidArgumentException
*/
public function testSplitTemplateNameInvalid($name)
public function testFromShortNotationInvalid($name)
{
$engine = new Engine($this->getContainerMock(), $this->getLoaderMock(), array());
$converter = new TemplateNameConverter($this->getContainerMock(), $this->getLoaderMock(), array());

$engine->splitTemplateName($name);
$converter->fromShortNotation($name);
}

public function getSplitTemplateNameInvalidTests()
public function getFromShortNotationInvalidTests()
{
return array(
array('BlogBundle:Post:index'),
Expand Down
21 changes: 12 additions & 9 deletions src/Symfony/Bundle/TwigBundle/Loader/Loader.php
Expand Up @@ -2,9 +2,10 @@

namespace Symfony\Bundle\TwigBundle\Loader;

use Symfony\Component\Templating\Engine;
use Symfony\Component\Templating\Storage\Storage;
use Symfony\Component\Templating\Storage\FileStorage;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameConverter;
use Symfony\Component\Templating\Loader\LoaderInterface;

/*
* This file is part of the Symfony package.
Expand All @@ -21,11 +22,13 @@
*/
class Loader implements \Twig_LoaderInterface
{
protected $engine;
protected $converter;
protected $loader;

public function setEngine(Engine $engine)
public function __construct(TemplateNameConverter $converter, LoaderInterface $loader)
{
$this->engine = $engine;
$this->converter = $converter;
$this->loader = $loader;
}

/**
Expand All @@ -41,13 +44,13 @@ public function getSource($name)
return $name->getContent();
}

list($name, $options) = $this->engine->splitTemplateName($name);
list($name, $options) = $this->converter->fromShortNotation($name);

if ('twig' !== $options['renderer']) {
throw new \LogicException(sprintf('A "%s" template cannot extend a "Twig" template.', $options['renderer']));
}

$template = $this->engine->getLoader()->load($name, $options);
$template = $this->loader->load($name, $options);

if (false === $template) {
throw new \InvalidArgumentException(sprintf('The template "%s" does not exist (renderer: %s).', $name, $options['renderer']));
Expand All @@ -69,7 +72,7 @@ public function getCacheKey($name)
return (string) $name;
}

list($name, $options) = $this->engine->splitTemplateName($name);
list($name, $options) = $this->converter->fromShortNotation($name);

return $name.'_'.serialize($options);
}
Expand All @@ -90,8 +93,8 @@ public function isFresh($name, $time)
return false;
}

list($name, $options) = $this->engine->splitTemplateName($name);
list($name, $options) = $this->converter->fromShortNotation($name);

return $this->engine->getLoader()->isFresh($name, $options, $time);
return $this->loader->isFresh($name, $options, $time);
}
}
5 changes: 2 additions & 3 deletions src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
Expand Up @@ -25,9 +25,8 @@
</service>

<service id="twig.loader" class="%twig.loader.class%">
<call method="setEngine">
<argument type="service" id="templating" />
</call>
<argument type="service" id="templating.name_converter" />
<argument type="service" id="templating.loader" />
</service>

<service id="twig.renderer" class="%twig.renderer.class%">
Expand Down
8 changes: 8 additions & 0 deletions src/Symfony/Component/Templating/Engine.php
Expand Up @@ -363,6 +363,14 @@ public function setRenderer($name, RendererInterface $renderer)
$renderer->setEngine($this);
}

/**
* Converts a short template notation to a template name and an array of options.
*
* @param string $name A short template template
* @param array $defaults An array of default options
*
* @return array An array composed of the template name and an array of options
*/
public function splitTemplateName($name)
{
if (false !== $pos = strpos($name, ':')) {
Expand Down

0 comments on commit 911dbe9

Please sign in to comment.