added the real template name when an error occurs in a Twig template

This commit is contained in:
Fabien Potencier 2011-11-07 20:03:35 +01:00
parent b957515a17
commit 47b888a957
8 changed files with 33 additions and 6 deletions

View File

@ -43,6 +43,10 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
* moved the data collector to the bridge * moved the data collector to the bridge
* replaced MessageLogger class with the one from Swiftmailer 4.1.3 * replaced MessageLogger class with the one from Swiftmailer 4.1.3
### TwigBundle
* added the real template name when an error occurs in a Twig template
### WebProfilerBundle ### WebProfilerBundle
* added a routing panel * added a routing panel

View File

@ -15,6 +15,7 @@ use Symfony\Bundle\TwigBundle\TwigEngine;
use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables; use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables;
use Symfony\Component\Templating\TemplateNameParserInterface; use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\HttpKernel\Debug\Stopwatch; use Symfony\Component\HttpKernel\Debug\Stopwatch;
use Symfony\Component\Config\FileLocatorInterface;
/** /**
* Times the time spent to render a template. * Times the time spent to render a template.
@ -33,9 +34,9 @@ class TimedTwigEngine extends TwigEngine
* @param GlobalVariables|null $globals A GlobalVariables instance or null * @param GlobalVariables|null $globals A GlobalVariables instance or null
* @param Stopwatch $stopwatch A Stopwatch instance * @param Stopwatch $stopwatch A Stopwatch instance
*/ */
public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser, Stopwatch $stopwatch, GlobalVariables $globals = null) public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser, FileLocatorInterface $locator, Stopwatch $stopwatch, GlobalVariables $globals = null)
{ {
parent::__construct($environment, $parser, $globals); parent::__construct($environment, $parser, $locator, $globals);
$this->stopwatch = $stopwatch; $this->stopwatch = $stopwatch;
} }

View File

@ -12,6 +12,7 @@
<service id="debug.templating.engine.twig" class="%debug.templating.engine.twig.class%" public="false"> <service id="debug.templating.engine.twig" class="%debug.templating.engine.twig.class%" public="false">
<argument type="service" id="twig" /> <argument type="service" id="twig" />
<argument type="service" id="templating.name_parser" /> <argument type="service" id="templating.name_parser" />
<argument type="service" id="templating.locator" />
<argument type="service" id="debug.stopwatch" /> <argument type="service" id="debug.stopwatch" />
<argument type="service" id="templating.globals" /> <argument type="service" id="templating.globals" />
</service> </service>

View File

@ -40,6 +40,7 @@
<service id="templating.engine.twig" class="%templating.engine.twig.class%" public="false"> <service id="templating.engine.twig" class="%templating.engine.twig.class%" public="false">
<argument type="service" id="twig" /> <argument type="service" id="twig" />
<argument type="service" id="templating.name_parser" /> <argument type="service" id="templating.name_parser" />
<argument type="service" id="templating.locator" />
<argument type="service" id="templating.globals" /> <argument type="service" id="templating.globals" />
</service> </service>

View File

@ -25,7 +25,8 @@ class TwigEngineTest extends TestCase
{ {
$environment = $this->getTwigEnvironment(); $environment = $this->getTwigEnvironment();
$container = $this->getContainer(); $container = $this->getContainer();
$engine = new TwigEngine($environment, new TemplateNameParser(), $app = new GlobalVariables($container)); $locator = $this->getMock('Symfony\Component\Config\FileLocatorInterface');
$engine = new TwigEngine($environment, new TemplateNameParser(), $locator, $app = new GlobalVariables($container));
$template = $this->getMock('\Twig_TemplateInterface'); $template = $this->getMock('\Twig_TemplateInterface');
@ -44,7 +45,8 @@ class TwigEngineTest extends TestCase
{ {
$environment = $this->getTwigEnvironment(); $environment = $this->getTwigEnvironment();
$container = new Container(); $container = new Container();
$engine = new TwigEngine($environment, new TemplateNameParser(), new GlobalVariables($container)); $locator = $this->getMock('Symfony\Component\Config\FileLocatorInterface');
$engine = new TwigEngine($environment, new TemplateNameParser(), $locator, new GlobalVariables($container));
$template = $this->getMock('\Twig_TemplateInterface'); $template = $this->getMock('\Twig_TemplateInterface');

View File

@ -13,8 +13,10 @@ namespace Symfony\Bundle\TwigBundle;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface; use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables; use Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\Templating\TemplateNameParserInterface; use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Config\FileLocatorInterface;
/** /**
* This engine knows how to render Twig templates. * This engine knows how to render Twig templates.
@ -25,6 +27,7 @@ class TwigEngine implements EngineInterface
{ {
protected $environment; protected $environment;
protected $parser; protected $parser;
protected $locator;
/** /**
* Constructor. * Constructor.
@ -33,10 +36,11 @@ class TwigEngine implements EngineInterface
* @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance
* @param GlobalVariables|null $globals A GlobalVariables instance or null * @param GlobalVariables|null $globals A GlobalVariables instance or null
*/ */
public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser, GlobalVariables $globals = null) public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser, FileLocatorInterface $locator, GlobalVariables $globals = null)
{ {
$this->environment = $environment; $this->environment = $environment;
$this->parser = $parser; $this->parser = $parser;
$this->locator = $locator;
if (null !== $globals) { if (null !== $globals) {
$environment->addGlobal('app', $globals); $environment->addGlobal('app', $globals);
@ -56,7 +60,19 @@ class TwigEngine implements EngineInterface
*/ */
public function render($name, array $parameters = array()) public function render($name, array $parameters = array())
{ {
return $this->load($name)->render($parameters); try {
return $this->load($name)->render($parameters);
} catch (\Exception $e) {
if ($name instanceof TemplateReference) {
try {
// try to get the real file name of the template where the error occurred
$e->setTemplateFile(sprintf('%s', $this->locator->locate($this->parser->parse($e->getTemplateFile()))));
} catch (\Exception $ex) {
}
}
throw $e;
}
} }
/** /**

View File

@ -76,6 +76,7 @@ class ExceptionControllerTest extends TestCase
$container->register('templating.engine.twig',$this->getMockClass('Symfony\\Bundle\\TwigBundle\\TwigEngine')) $container->register('templating.engine.twig',$this->getMockClass('Symfony\\Bundle\\TwigBundle\\TwigEngine'))
->addArgument($this->getMock('Twig_Environment')) ->addArgument($this->getMock('Twig_Environment'))
->addArgument($this->getMock('Symfony\\Component\\Templating\\TemplateNameParserInterface')) ->addArgument($this->getMock('Symfony\\Component\\Templating\\TemplateNameParserInterface'))
->addArgument(new Definition($this->getMockClass('Symfony\Component\Config\FileLocatorInterface')))
->addArgument($this->getMock('Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables', array(), array($this->getMock('Symfony\\Component\\DependencyInjection\\Container')))); ->addArgument($this->getMock('Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables', array(), array($this->getMock('Symfony\\Component\\DependencyInjection\\Container'))));
$container->setAlias('templating', 'templating.engine.twig'); $container->setAlias('templating', 'templating.engine.twig');
$container->setParameter('kernel.bundles', array()); $container->setParameter('kernel.bundles', array());

View File

@ -60,6 +60,7 @@ class WebProfilerExtensionTest extends TestCase
$this->container->register('templating.engine.twig', $this->getMockClass('Symfony\\Bundle\\TwigBundle\\TwigEngine')) $this->container->register('templating.engine.twig', $this->getMockClass('Symfony\\Bundle\\TwigBundle\\TwigEngine'))
->addArgument(new Definition($this->getMockClass('Twig_Environment'))) ->addArgument(new Definition($this->getMockClass('Twig_Environment')))
->addArgument(new Definition($this->getMockClass('Symfony\\Component\\Templating\\TemplateNameParserInterface'))) ->addArgument(new Definition($this->getMockClass('Symfony\\Component\\Templating\\TemplateNameParserInterface')))
->addArgument(new Definition($this->getMockClass('Symfony\Component\Config\FileLocatorInterface')))
->addArgument(new Definition($this->getMockClass('Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables'), array(new Definition($this->getMockClass('Symfony\\Component\\DependencyInjection\\Container'))))); ->addArgument(new Definition($this->getMockClass('Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables'), array(new Definition($this->getMockClass('Symfony\\Component\\DependencyInjection\\Container')))));
$this->container->setParameter('kernel.bundles', array()); $this->container->setParameter('kernel.bundles', array());
$this->container->setParameter('kernel.cache_dir', __DIR__); $this->container->setParameter('kernel.cache_dir', __DIR__);