removed the dependency on the container for exception handling

This commit is contained in:
Fabien Potencier 2012-12-13 15:44:37 +01:00
parent 2f4ac5e3d1
commit 35d63df044
7 changed files with 62 additions and 33 deletions

View File

@ -4,6 +4,7 @@ CHANGELOG
2.2.0 2.2.0
----- -----
* moved the exception controller to be a service (`twig.controller.exception:showAction` vs `Symfony\\Bundle\\TwigBundle\\Controller\\ExceptionController::showAction`)
* added support for multiple loaders via the "twig.loader" tag. * added support for multiple loaders via the "twig.loader" tag.
* added automatic registration of namespaced paths for registered bundles * added automatic registration of namespaced paths for registered bundles
* added support for namespaced paths * added support for namespaced paths

View File

@ -13,9 +13,9 @@ namespace Symfony\Bundle\TwigBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface; use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference; use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpKernel\Exception\FlattenException; use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
/** /**
@ -23,8 +23,17 @@ use Symfony\Component\HttpFoundation\Response;
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
class ExceptionController extends ContainerAware class ExceptionController
{ {
protected $twig;
protected $debug;
public function __construct(\Twig_Environment $twig, $debug)
{
$this->twig = $twig;
$this->debug = $debug;
}
/** /**
* Converts an Exception to a Response. * Converts an Exception to a Response.
* *
@ -36,17 +45,16 @@ class ExceptionController extends ContainerAware
* *
* @throws \InvalidArgumentException When the exception template does not exist * @throws \InvalidArgumentException When the exception template does not exist
*/ */
public function showAction(FlattenException $exception, DebugLoggerInterface $logger = null, $format = 'html') public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null, $format = 'html')
{ {
$this->container->get('request')->setRequestFormat($format); $request->setRequestFormat($format);
$currentContent = $this->getAndCleanOutputBuffering(); $currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
$templating = $this->container->get('templating');
$code = $exception->getStatusCode(); $code = $exception->getStatusCode();
return $templating->renderResponse( return new Response($this->twig->render(
$this->findTemplate($templating, $format, $code, $this->container->get('kernel')->isDebug()), $this->findTemplate($request, $format, $code, $this->debug),
array( array(
'status_code' => $code, 'status_code' => $code,
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '', 'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
@ -54,19 +62,17 @@ class ExceptionController extends ContainerAware
'logger' => $logger, 'logger' => $logger,
'currentContent' => $currentContent, 'currentContent' => $currentContent,
) )
); ));
} }
/** /**
* @return string * @return string
*/ */
protected function getAndCleanOutputBuffering() protected function getAndCleanOutputBuffering($startObLevel)
{ {
// ob_get_level() never returns 0 on some Windows configurations, so if // ob_get_level() never returns 0 on some Windows configurations, so if
// the level is the same two times in a row, the loop should be stopped. // the level is the same two times in a row, the loop should be stopped.
$previousObLevel = null; $previousObLevel = null;
$startObLevel = $this->container->get('request')->headers->get('X-Php-Ob-Level', -1);
$currentContent = ''; $currentContent = '';
while (($obLevel = ob_get_level()) > $startObLevel && $obLevel !== $previousObLevel) { while (($obLevel = ob_get_level()) > $startObLevel && $obLevel !== $previousObLevel) {
@ -78,14 +84,14 @@ class ExceptionController extends ContainerAware
} }
/** /**
* @param EngineInterface $templating * @param Request $request
* @param string $format * @param string $format
* @param integer $code An HTTP response status code * @param integer $code An HTTP response status code
* @param Boolean $debug * @param Boolean $debug
* *
* @return TemplateReference * @return TemplateReference
*/ */
protected function findTemplate($templating, $format, $code, $debug) protected function findTemplate(Request $request, $format, $code, $debug)
{ {
$name = $debug ? 'exception' : 'error'; $name = $debug ? 'exception' : 'error';
if ($debug && 'html' == $format) { if ($debug && 'html' == $format) {
@ -95,19 +101,19 @@ class ExceptionController extends ContainerAware
// when not in debug, try to find a template for the specific HTTP status code and format // when not in debug, try to find a template for the specific HTTP status code and format
if (!$debug) { if (!$debug) {
$template = new TemplateReference('TwigBundle', 'Exception', $name.$code, $format, 'twig'); $template = new TemplateReference('TwigBundle', 'Exception', $name.$code, $format, 'twig');
if ($templating->exists($template)) { if ($this->twig->getLoader()->exists($template)) {
return $template; return $template;
} }
} }
// try to find a template for the given format // try to find a template for the given format
$template = new TemplateReference('TwigBundle', 'Exception', $name, $format, 'twig'); $template = new TemplateReference('TwigBundle', 'Exception', $name, $format, 'twig');
if ($templating->exists($template)) { if ($this->twig->getLoader()->exists($template)) {
return $template; return $template;
} }
// default to a generic HTML exception // default to a generic HTML exception
$this->container->get('request')->setRequestFormat('html'); $request->setRequestFormat('html');
return new TemplateReference('TwigBundle', 'Exception', $name, 'html', 'twig'); return new TemplateReference('TwigBundle', 'Exception', $name, 'html', 'twig');
} }

View File

@ -34,7 +34,7 @@ class Configuration implements ConfigurationInterface
$rootNode $rootNode
->children() ->children()
->scalarNode('exception_controller')->defaultValue('Symfony\\Bundle\\TwigBundle\\Controller\\ExceptionController::showAction')->end() ->scalarNode('exception_controller')->defaultValue('twig.controller.exception:showAction')->end()
->end() ->end()
; ;

View File

@ -21,6 +21,7 @@
<parameter key="twig.form.renderer.class">Symfony\Bridge\Twig\Form\TwigRenderer</parameter> <parameter key="twig.form.renderer.class">Symfony\Bridge\Twig\Form\TwigRenderer</parameter>
<parameter key="twig.translation.extractor.class">Symfony\Bridge\Twig\Translation\TwigExtractor</parameter> <parameter key="twig.translation.extractor.class">Symfony\Bridge\Twig\Translation\TwigExtractor</parameter>
<parameter key="twig.exception_listener.class">Symfony\Component\HttpKernel\EventListener\ExceptionListener</parameter> <parameter key="twig.exception_listener.class">Symfony\Component\HttpKernel\EventListener\ExceptionListener</parameter>
<parameter key="twig.controller.exception.class">Symfony\Bundle\TwigBundle\Controller\ExceptionController</parameter>
</parameters> </parameters>
<services> <services>
@ -111,5 +112,10 @@
<argument>%twig.exception_listener.controller%</argument> <argument>%twig.exception_listener.controller%</argument>
<argument type="service" id="logger" on-invalid="null" /> <argument type="service" id="logger" on-invalid="null" />
</service> </service>
<service id="twig.controller.exception" class="%twig.controller.exception.class%">
<argument type="service" id="twig" />
<argument>%kernel.debug%</argument>
</service>
</services> </services>
</container> </container>

View File

@ -12,27 +12,37 @@
namespace Symfony\Bundle\WebProfilerBundle\Controller; namespace Symfony\Bundle\WebProfilerBundle\Controller;
use Symfony\Component\HttpKernel\Exception\FlattenException; use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
/** /**
* ExceptionController. * ExceptionController.
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
class ExceptionController extends BaseExceptionController class ExceptionController
{ {
/** protected $twig;
* {@inheritdoc} protected $debug;
*/
public function showAction(FlattenException $exception, DebugLoggerInterface $logger = null, $format = 'html') public function __construct(\Twig_Environment $twig, $debug)
{
$this->twig = $twig;
$this->debug = $debug;
}
/**
* Converts an Exception to a Response.
*
* @param FlattenException $exception A FlattenException instance
*
* @return Response
*/
public function showAction(FlattenException $exception)
{ {
$template = $this->container->get('kernel')->isDebug() ? 'exception' : 'error';
$code = $exception->getStatusCode(); $code = $exception->getStatusCode();
return $this->container->get('templating')->renderResponse( return new Response($this->twig->render(
'TwigBundle:Exception:'.$template.'.html.twig', '@Twig/Exception/'.($this->debug ? 'exception' : 'error').'.html.twig',
array( array(
'status_code' => $code, 'status_code' => $code,
'status_text' => Response::$statusTexts[$code], 'status_text' => Response::$statusTexts[$code],
@ -40,6 +50,6 @@ class ExceptionController extends BaseExceptionController
'logger' => null, 'logger' => null,
'currentContent' => '', 'currentContent' => '',
) )
); ));
} }
} }

View File

@ -7,6 +7,7 @@
<parameters> <parameters>
<parameter key="web_profiler.controller.profiler.class">Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController</parameter> <parameter key="web_profiler.controller.profiler.class">Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController</parameter>
<parameter key="web_profiler.controller.router.class">Symfony\Bundle\WebProfilerBundle\Controller\RouterController</parameter> <parameter key="web_profiler.controller.router.class">Symfony\Bundle\WebProfilerBundle\Controller\RouterController</parameter>
<parameter key="web_profiler.controller.exception.class">Symfony\Bundle\WebProfilerBundle\Controller\ExceptionController</parameter>
</parameters> </parameters>
<services> <services>
@ -23,5 +24,10 @@
<argument type="service" id="twig" /> <argument type="service" id="twig" />
<argument type="service" id="router" on-invalid="null" /> <argument type="service" id="router" on-invalid="null" />
</service> </service>
<service id="web_profiler.controller.exception" class="%web_profiler.controller.exception.class%">
<argument type="service" id="twig" />
<argument>%kernel.debug%</argument>
</service>
</services> </services>
</container> </container>

View File

@ -28,7 +28,7 @@
</p> </p>
{% else %} {% else %}
<div class="sf-reset"> <div class="sf-reset">
{% render 'WebProfilerBundle:Exception:show' with { 'exception': collector.exception, 'format': 'html' } %} {% render 'web_profiler.controller.exception:showAction' with { 'exception': collector.exception, 'format': 'html' } %}
</div> </div>
{% endif %} {% endif %}
{% endblock %} {% endblock %}