ExceptionController.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\TwigBundle\Controller;
  11. use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
  12. use Symfony\Component\DependencyInjection\ContainerAware;
  13. use Symfony\Component\HttpKernel\Exception\FlattenException;
  14. use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
  15. use Symfony\Component\HttpFoundation\Response;
  16. /**
  17. * ExceptionController.
  18. *
  19. * @author Fabien Potencier <fabien@symfony.com>
  20. */
  21. class ExceptionController extends ContainerAware
  22. {
  23. /**
  24. * Converts an Exception to a Response.
  25. *
  26. * @param FlattenException $exception A FlattenException instance
  27. * @param DebugLoggerInterface $logger A DebugLoggerInterface instance
  28. * @param string $format The format to use for rendering (html, xml, ...)
  29. *
  30. * @throws \InvalidArgumentException When the exception template does not exist
  31. */
  32. public function showAction(FlattenException $exception, DebugLoggerInterface $logger = null, $format = 'html')
  33. {
  34. $this->container->get('request')->setRequestFormat($format);
  35. $currentContent = $this->getAndCleanOutputBuffering();
  36. $templating = $this->container->get('templating');
  37. $code = $exception->getStatusCode();
  38. $response = $templating->renderResponse(
  39. $this->findTemplate($templating, $format, $code, $this->container->get('kernel')->isDebug()),
  40. array(
  41. 'status_code' => $code,
  42. 'status_text' => Response::$statusTexts[$code],
  43. 'exception' => $exception,
  44. 'logger' => $logger,
  45. 'currentContent' => $currentContent,
  46. )
  47. );
  48. $response->setStatusCode($code);
  49. $response->headers->replace($exception->getHeaders());
  50. return $response;
  51. }
  52. protected function getAndCleanOutputBuffering()
  53. {
  54. // ob_get_level() never returns 0 on some Windows configurations, so if
  55. // the level is the same two times in a row, the loop should be stopped.
  56. $previousObLevel = null;
  57. $startObLevel = $this->container->get('request')->headers->get('X-Php-Ob-Level', -1);
  58. $currentContent = '';
  59. while (($obLevel = ob_get_level()) > $startObLevel && $obLevel !== $previousObLevel) {
  60. $previousObLevel = $obLevel;
  61. $currentContent .= ob_get_clean();
  62. }
  63. return $currentContent;
  64. }
  65. protected function findTemplate($templating, $format, $code, $debug)
  66. {
  67. $name = $debug ? 'exception' : 'error';
  68. if ($debug && 'html' == $format) {
  69. $name = 'exception_full';
  70. }
  71. // when not in debug, try to find a template for the specific HTTP status code and format
  72. if (!$debug) {
  73. $template = new TemplateReference('TwigBundle', 'Exception', $name.$code, $format, 'twig');
  74. if ($templating->exists($template)) {
  75. return $template;
  76. }
  77. }
  78. // try to find a template for the given format
  79. $template = new TemplateReference('TwigBundle', 'Exception', $name, $format, 'twig');
  80. if ($templating->exists($template)) {
  81. return $template;
  82. }
  83. // default to a generic HTML exception
  84. $this->container->get('request')->setRequestFormat('html');
  85. return new TemplateReference('TwigBundle', 'Exception', $name, 'html', 'twig');
  86. }
  87. }