[FrameworkBundle] refactored Exception management
This commit is contained in:
parent
955fd40dd8
commit
d5069fc594
@ -3,10 +3,7 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller;
|
||||
use Symfony\Bundle\FrameworkBundle\Debug\ExceptionFormatter;
|
||||
use Symfony\Components\HttpFoundation\Request;
|
||||
use Symfony\Components\HttpFoundation\Response;
|
||||
use Symfony\Components\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Bundle\FrameworkBundle\Debug\ExceptionManager;
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony framework.
|
||||
@ -27,60 +24,19 @@ class ExceptionController extends Controller
|
||||
/**
|
||||
* Converts an Exception to a Response.
|
||||
*
|
||||
* @param \Exception $exception An Exception instance
|
||||
* @param Request $request The original Request instance
|
||||
* @param array $logs An array of logs
|
||||
* @param ExceptionManager $manager An ExceptionManager instance
|
||||
*
|
||||
* @throws \InvalidArgumentException When the exception template does not exist
|
||||
*/
|
||||
public function exceptionAction(\Exception $exception, Request $originalRequest, array $logs)
|
||||
public function exceptionAction(ExceptionManager $manager)
|
||||
{
|
||||
$template = $this->container->getParameter('kernel.debug') ? 'exception' : 'error';
|
||||
$this['request']->setRequestFormat($manager->getFormat());
|
||||
|
||||
$format = $format = $originalRequest->getRequestFormat();
|
||||
|
||||
// when using CLI, we force the format to be TXT
|
||||
if (0 === strncasecmp(PHP_SAPI, 'cli', 3)) {
|
||||
$format = 'txt';
|
||||
}
|
||||
|
||||
$template = $this['templating']->getLoader()->load($template, array(
|
||||
'bundle' => 'FrameworkBundle',
|
||||
'controller' => 'Exception',
|
||||
'format' => '.'.$format,
|
||||
));
|
||||
|
||||
if (false === $template) {
|
||||
throw new \InvalidArgumentException(sprintf('The exception template for format "%s" does not exist.', $format));
|
||||
}
|
||||
|
||||
$code = $exception instanceof HttpException ? $exception->getCode() : 500;
|
||||
$text = Response::$statusTexts[$code];
|
||||
$formatter = new ExceptionFormatter($this->container->getParameterBag()->has('debug.file_link_format') ? $this->container->getParameter('debug.file_link_format') : null, $this->container->getParameter('kernel.charset'));
|
||||
$message = null === $exception->getMessage() ? 'n/a' : $exception->getMessage();
|
||||
$name = get_class($exception);
|
||||
$traces = $formatter->getTraces($exception, 'html' === $format ? 'html' : 'text');
|
||||
$charset = $this->container->getParameter('kernel.charset');
|
||||
|
||||
$errors = 0;
|
||||
foreach ($logs as $log) {
|
||||
if ('ERR' === $log['priorityName']) {
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
$currentContent = '';
|
||||
while (false !== $content = ob_get_clean()) {
|
||||
$currentContent .= $content;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
require $template;
|
||||
$content = ob_get_clean();
|
||||
|
||||
$response = $this['response'];
|
||||
$response->setStatusCode($code);
|
||||
$response->setContent($content);
|
||||
$response = $this->render(
|
||||
'FrameworkBundle:Exception:'.($this['kernel']->isDebug() ? 'exception' : 'error'),
|
||||
array('manager' => $manager)
|
||||
);
|
||||
$response->setStatusCode($manager->getStatusCode());
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
@ -1,179 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Debug;
|
||||
|
||||
use Symfony\Components\DependencyInjection\ContainerInterface;
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ExceptionFormatter.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class ExceptionFormatter
|
||||
{
|
||||
protected $fileLinkFormat;
|
||||
protected $charset;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $fileLinkFormat The format for links to source files
|
||||
* @param string $charset The current charset
|
||||
*/
|
||||
public function __construct($fileLinkFormat, $charset = 'UTF-8')
|
||||
{
|
||||
$this->fileLinkFormat = null !== $fileLinkFormat ? $fileLinkFormat : ini_get('xdebug.file_link_format');
|
||||
$this->charset = $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of exception traces.
|
||||
*
|
||||
* @param Exception $exception An Exception implementation instance
|
||||
* @param string $format The trace format (txt or html)
|
||||
*
|
||||
* @return array An array of traces
|
||||
*/
|
||||
public function getTraces(\Exception $exception, $format = 'txt')
|
||||
{
|
||||
$traceData = $exception->getTrace();
|
||||
array_unshift($traceData, array(
|
||||
'function' => '',
|
||||
'file' => $exception->getFile() != null ? $exception->getFile() : null,
|
||||
'line' => $exception->getLine() != null ? $exception->getLine() : null,
|
||||
'args' => array(),
|
||||
));
|
||||
|
||||
$traces = array();
|
||||
if ($format == 'html') {
|
||||
$lineFormat = 'at <strong>%s%s%s</strong>(%s)<br />in <em>%s</em> line %s <a href="#" onclick="toggle(\'%s\'); return false;">...</a><br /><ul class="code" id="%s" style="display: %s">%s</ul>';
|
||||
} else {
|
||||
$lineFormat = 'at %s%s%s(%s) in %s line %s';
|
||||
}
|
||||
|
||||
for ($i = 0, $count = count($traceData); $i < $count; $i++) {
|
||||
$line = isset($traceData[$i]['line']) ? $traceData[$i]['line'] : null;
|
||||
$file = isset($traceData[$i]['file']) ? $traceData[$i]['file'] : null;
|
||||
$args = isset($traceData[$i]['args']) ? $traceData[$i]['args'] : array();
|
||||
$traces[] = sprintf($lineFormat,
|
||||
(isset($traceData[$i]['class']) ? $traceData[$i]['class'] : ''),
|
||||
(isset($traceData[$i]['type']) ? $traceData[$i]['type'] : ''),
|
||||
$traceData[$i]['function'],
|
||||
$this->formatArgs($args, false, $format),
|
||||
$this->formatFile($file, $line, $format, null === $file ? 'n/a' : $file),
|
||||
null === $line ? 'n/a' : $line,
|
||||
'trace_'.$i,
|
||||
'trace_'.$i,
|
||||
$i == 0 ? 'block' : 'none',
|
||||
$this->fileExcerpt($file, $line)
|
||||
);
|
||||
}
|
||||
|
||||
return $traces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an excerpt of a code file around the given line number.
|
||||
*
|
||||
* @param string $file A file path
|
||||
* @param int $line The selected line number
|
||||
*
|
||||
* @return string An HTML string
|
||||
*/
|
||||
protected function fileExcerpt($file, $line)
|
||||
{
|
||||
if (is_readable($file)) {
|
||||
$content = preg_split('#<br />#', highlight_file($file, true));
|
||||
|
||||
$lines = array();
|
||||
for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; $i++) {
|
||||
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'>'.$content[$i - 1].'</li>';
|
||||
}
|
||||
|
||||
return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an array as a string.
|
||||
*
|
||||
* @param array $args The argument array
|
||||
* @param boolean $single
|
||||
* @param string $format The format string (html or txt)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatArgs($args, $single = false, $format = 'html')
|
||||
{
|
||||
$result = array();
|
||||
|
||||
$single and $args = array($args);
|
||||
|
||||
foreach ($args as $key => $value) {
|
||||
if (is_object($value)) {
|
||||
$formattedValue = ($format == 'html' ? '<em>object</em>' : 'object').sprintf("('%s')", get_class($value));
|
||||
} else if (is_array($value)) {
|
||||
$formattedValue = ($format == 'html' ? '<em>array</em>' : 'array').sprintf("(%s)", $this->formatArgs($value));
|
||||
} else if (is_string($value)) {
|
||||
$formattedValue = ($format == 'html' ? sprintf("'%s'", $this->escape($value)) : "'$value'");
|
||||
} else if (null === $value) {
|
||||
$formattedValue = ($format == 'html' ? '<em>null</em>' : 'null');
|
||||
} else {
|
||||
$formattedValue = $value;
|
||||
}
|
||||
|
||||
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escape($key), $formattedValue);
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a file path.
|
||||
*
|
||||
* @param string $file An absolute file path
|
||||
* @param integer $line The line number
|
||||
* @param string $format The output format (txt or html)
|
||||
* @param string $text Use this text for the link rather than the file path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatFile($file, $line, $format = 'html', $text = null)
|
||||
{
|
||||
if (null === $text) {
|
||||
$text = $file;
|
||||
}
|
||||
|
||||
if ('html' === $format && $file && $line && $this->fileLinkFormat) {
|
||||
$link = strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
|
||||
$text = sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', $link, $text);
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a string value with html entities
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function escape($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return htmlspecialchars($value, ENT_QUOTES, $this->charset);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Controller;
|
||||
namespace Symfony\Bundle\FrameworkBundle\Debug;
|
||||
|
||||
use Symfony\Components\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Components\EventDispatcher\EventDispatcher;
|
||||
@ -28,12 +28,11 @@ class ExceptionListener
|
||||
protected $controller;
|
||||
protected $logger;
|
||||
|
||||
public function __construct(ContainerInterface $container, LoggerInterface $logger = null, $controller)
|
||||
public function __construct(ContainerInterface $container, $controller, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->logger = $logger;
|
||||
|
||||
$this->controller = $controller;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,24 +54,21 @@ class ExceptionListener
|
||||
$exception = $event->getParameter('exception');
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->err(sprintf('%s (uncaught %s exception)', $exception->getMessage(), get_class($exception)));
|
||||
$this->logger->err(sprintf('%s: %s (uncaught exception)', get_class($exception), $exception->getMessage()));
|
||||
}
|
||||
|
||||
$parameters = array(
|
||||
'_controller' => $this->controller,
|
||||
'exception' => $exception,
|
||||
'originalRequest' => $event->getParameter('request'),
|
||||
'logs' => $this->container->has('zend.logger.writer.debug') ? $this->container->get('zend.logger.writer.debug')->getLogs() : array(),
|
||||
$class = $this->container->getParameter('exception_manager.class');
|
||||
$logger = $this->container->has('logger.debug') ? $this->container->get('logger.debug') : null;
|
||||
|
||||
$attributes = array(
|
||||
'_controller' => $this->controller,
|
||||
'manager' => new $class($exception, $event->getParameter('request'), $logger),
|
||||
);
|
||||
|
||||
$request = $event->getParameter('request')->duplicate(null, null, $parameters);
|
||||
$request = $event->getParameter('request')->duplicate(null, null, $attributes);
|
||||
|
||||
try {
|
||||
$response = $event->getSubject()->handle($request, HttpKernelInterface::SUB_REQUEST, true);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->err(sprintf('%s: %s', get_class($exception), $exception->getMessage()));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->err(sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $e->getMessage()));
|
137
src/Symfony/Bundle/FrameworkBundle/Debug/ExceptionManager.php
Normal file
137
src/Symfony/Bundle/FrameworkBundle/Debug/ExceptionManager.php
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Debug;
|
||||
|
||||
use Symfony\Components\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Components\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Components\HttpFoundation\Request;
|
||||
use Symfony\Components\HttpFoundation\Response;
|
||||
use Symfony\Components\HttpKernel\Log\DebugLoggerInterface;
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ExceptionManager.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class ExceptionManager
|
||||
{
|
||||
protected $exception;
|
||||
protected $request;
|
||||
protected $logger;
|
||||
protected $currentContent;
|
||||
|
||||
public function __construct(\Exception $exception, Request $request, DebugLoggerInterface $logger)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
$this->request = $request;
|
||||
$this->logger = $logger;
|
||||
|
||||
$this->currentContent = '';
|
||||
while (false !== $content = ob_get_clean()) {
|
||||
$this->currentContent .= $content;
|
||||
}
|
||||
}
|
||||
|
||||
public function getException()
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
|
||||
public function getCurrentContent()
|
||||
{
|
||||
return $this->currentContent;
|
||||
}
|
||||
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
public function getLogs()
|
||||
{
|
||||
return $this->logger->getLogs();
|
||||
}
|
||||
|
||||
public function countErrors()
|
||||
{
|
||||
$errors = 0;
|
||||
foreach ($this->logger->getLogs() as $log) {
|
||||
if ('ERR' === $log['priorityName']) {
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
$format = $this->request->getRequestFormat();
|
||||
|
||||
// when using CLI, we force the format to be TXT
|
||||
if (0 === strncasecmp(PHP_SAPI, 'cli', 3)) {
|
||||
$format = 'txt';
|
||||
}
|
||||
|
||||
return $format;
|
||||
}
|
||||
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->exception instanceof HttpException ? $this->exception->getCode() : 500;
|
||||
}
|
||||
|
||||
public function getStatusText()
|
||||
{
|
||||
return Response::$statusTexts[$this->getStatusCode()];
|
||||
}
|
||||
|
||||
public function getMessage()
|
||||
{
|
||||
return null === $this->exception->getMessage() ? 'n/a' : $this->exception->getMessage();
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return get_class($this->exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of exception traces.
|
||||
*
|
||||
* @return array An array of traces
|
||||
*/
|
||||
public function getTraces()
|
||||
{
|
||||
$traces = array();
|
||||
$traces[] = array(
|
||||
'class' => '',
|
||||
'type' => '',
|
||||
'function' => '',
|
||||
'file' => $this->exception->getFile(),
|
||||
'line' => $this->exception->getLine(),
|
||||
'args' => array(),
|
||||
);
|
||||
foreach ($this->exception->getTrace() as $entry) {
|
||||
$traces[] = array(
|
||||
'class' => isset($entry['class']) ? $entry['class'] : '',
|
||||
'type' => isset($entry['type']) ? $entry['type'] : '',
|
||||
'function' => $entry['function'],
|
||||
'file' => isset($entry['file']) ? $entry['file'] : null,
|
||||
'line' => isset($entry['line']) ? $entry['line'] : null,
|
||||
'args' => isset($entry['args']) ? $entry['args'] : array(),
|
||||
);
|
||||
}
|
||||
|
||||
return $traces;
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@
|
||||
<parameter key="templating.helper.router.class">Symfony\Bundle\FrameworkBundle\Templating\Helper\RouterHelper</parameter>
|
||||
<parameter key="templating.helper.request.class">Symfony\Bundle\FrameworkBundle\Templating\Helper\RequestHelper</parameter>
|
||||
<parameter key="templating.helper.session.class">Symfony\Bundle\FrameworkBundle\Templating\Helper\SessionHelper</parameter>
|
||||
<parameter key="templating.helper.code.class">Symfony\Bundle\FrameworkBundle\Templating\Helper\CodeHelper</parameter>
|
||||
<parameter key="templating.output_escaper">false</parameter>
|
||||
<parameter key="templating.assets.version">null</parameter>
|
||||
<parameter key="debug.file_link_format">null</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
@ -86,6 +88,11 @@
|
||||
<argument type="service" id="controller_resolver" />
|
||||
</service>
|
||||
|
||||
<service id="templating.helper.code" class="%templating.helper.code.class%">
|
||||
<tag name="templating.helper" alias="code" />
|
||||
<argument>%debug.file_link_format%</argument>
|
||||
</service>
|
||||
|
||||
<service id="templating.loader" alias="templating.loader.filesystem" />
|
||||
|
||||
<service id="templating" alias="templating.engine" />
|
||||
|
@ -9,8 +9,9 @@
|
||||
<parameter key="controller_resolver.class">Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver</parameter>
|
||||
<parameter key="controller_name_converter.class">Symfony\Bundle\FrameworkBundle\Controller\ControllerNameConverter</parameter>
|
||||
<parameter key="response_listener.class">Symfony\Components\HttpKernel\ResponseListener</parameter>
|
||||
<parameter key="exception_listener.class">Symfony\Bundle\FrameworkBundle\Controller\ExceptionListener</parameter>
|
||||
<parameter key="exception_listener.class">Symfony\Bundle\FrameworkBundle\Debug\ExceptionListener</parameter>
|
||||
<parameter key="exception_listener.controller">Symfony\Bundle\FrameworkBundle\Controller\ExceptionController::exceptionAction</parameter>
|
||||
<parameter key="exception_manager.class">Symfony\Bundle\FrameworkBundle\Debug\ExceptionManager</parameter>
|
||||
<parameter key="esi.class">Symfony\Components\HttpKernel\Cache\Esi</parameter>
|
||||
<parameter key="esi_listener.class">Symfony\Components\HttpKernel\Cache\EsiListener</parameter>
|
||||
</parameters>
|
||||
@ -47,8 +48,8 @@
|
||||
<service id="exception_listener" class="%exception_listener.class%">
|
||||
<tag name="kernel.listener" />
|
||||
<argument type="service" id="service_container" />
|
||||
<argument type="service" id="logger" on-invalid="null" />
|
||||
<argument>%exception_listener.controller%</argument>
|
||||
<argument type="service" id="logger" on-invalid="null" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
@ -1 +1 @@
|
||||
<?php include sfException::getTemplatePathForError('xml', false) ?>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:error.xml', array('manager' => $manager)) ?>
|
||||
|
@ -1,3 +1 @@
|
||||
/*
|
||||
<?php echo $code.' '.$text."\n" ?>
|
||||
*/
|
||||
<?php echo $view->render('FrameworkBundle:Exception:error.js', array('manager' => $manager)) ?>
|
||||
|
@ -1,3 +1,3 @@
|
||||
/*
|
||||
<?php echo $code.' '.$text."\n" ?>
|
||||
<?php echo $manager->getStatusCode().' '.$manager->getStatusText()."\n" ?>
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php echo json_encode(array(
|
||||
'error' => array(
|
||||
'code' => $code,
|
||||
'message' => $text,
|
||||
'code' => $manager->getStatusCode(),
|
||||
'message' => $manager->getStatusText(),
|
||||
))) ?>
|
||||
|
@ -27,7 +27,7 @@
|
||||
<img alt="page not found" class="sfTMessageIcon" src="<?php echo $path ?>/sf/sf_default/images/icons/tools48.png" height="48" width="48" />
|
||||
<div class="sfTMessageWrap">
|
||||
<h1>Oops! An Error Occurred</h1>
|
||||
<h5>The server returned a "<?php echo $code ?> <?php echo $text ?>".</h5>
|
||||
<h5>The server returned a "<?php echo $manager->getStatusCode() ?> <?php echo $manager->getStatusText() ?>".</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1 +1 @@
|
||||
<?php include sfException::getTemplatePathForError('xml', false) ?>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:error.xml', array('manager' => $manager)) ?>
|
||||
|
@ -1,7 +1,7 @@
|
||||
Oops! An Error Occurred
|
||||
=======================
|
||||
|
||||
The server returned a "<?php echo $code ?> <?php echo $text ?>".
|
||||
The server returned a "<?php echo $manager->getStatusCode() ?> <?php echo $manager->getStatusText() ?>".
|
||||
|
||||
Please e-mail us at [email] and let us know what you were doing when this
|
||||
error occurred. We will fix it as soon as possible. Sorry for any
|
||||
|
@ -1,2 +1,2 @@
|
||||
<?php echo sprintf('<?xml version="1.0" encoding="%s" ?>', $charset)."\n" ?>
|
||||
<error code="<?php echo $code ?>" message="<?php echo $text ?>" />
|
||||
<?php echo sprintf('<?xml version="1.0" encoding="%s" ?>', $view->getCharset())."\n" ?>
|
||||
<error code="<?php echo $manager->getStatusCode() ?>" message="<?php echo $manager->getStatusText() ?>" />
|
||||
|
@ -1 +1 @@
|
||||
<?php include sfException::getTemplatePathForError('xml', true) ?>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:exception.xml', array('manager' => $manager)) ?>
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
<?php echo $code.' '.$text."\n" ?>
|
||||
|
||||
<?php echo $name."\n" ?>
|
||||
<?php echo $message."\n" ?>
|
||||
|
||||
<?php foreach ($traces as $trace): ?>
|
||||
<?php echo $trace."\n" ?>
|
||||
<?php endforeach; ?>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:exception.txt', array('manager' => $manager)) ?>
|
||||
*/
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
<?php echo $code.' '.$text."\n" ?>
|
||||
|
||||
<?php echo $name."\n" ?>
|
||||
<?php echo $message."\n" ?>
|
||||
|
||||
<?php foreach ($traces as $trace): ?>
|
||||
<?php echo $trace."\n" ?>
|
||||
<?php endforeach; ?>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:exception.txt', array('manager' => $manager)) ?>
|
||||
*/
|
||||
|
@ -1,10 +1,9 @@
|
||||
<?php echo json_encode(array(
|
||||
'error' => array(
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'code' => $manager->getStatusCode(),
|
||||
'message' => $manager->getMessage(),
|
||||
'debug' => array(
|
||||
'name' => $name,
|
||||
'message' => $message,
|
||||
'traces' => $traces,
|
||||
'name' => $manager->getName(),
|
||||
'traces' => $manager->getTraces(),
|
||||
),
|
||||
))) ?>
|
||||
|
@ -1,34 +1,10 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $charset ?>"/>
|
||||
<title><?php echo htmlspecialchars($message, ENT_QUOTES, $charset) ?> (<?php echo $code ?> <?php echo $text ?>)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $view->getCharset() ?>"/>
|
||||
<title><?php echo htmlspecialchars($manager->getMessage(), ENT_QUOTES, $view->getCharset()) ?> (<?php echo $manager->getStatusCode() ?> <?php echo $manager->getStatusText() ?>)</title>
|
||||
<style type="text/css">
|
||||
body { margin: 0; padding: 0; margin-top: 30px; background-color: #eee }
|
||||
body, td, th { font: 11px Verdana, Arial, sans-serif; color: #333 }
|
||||
a { color: #333 }
|
||||
h1 { margin: 0; margin-top: 4px; font-weight: normal; font-size: 170%; letter-spacing: -0.03em; }
|
||||
h2 { margin: 0; padding: 0; font-size: 90%; font-weight: normal; letter-spacing: -0.02em; }
|
||||
h3 { margin: 0; padding: 0; margin-bottom: 10px; font-size: 110% }
|
||||
ul { padding-left: 20px; list-style: decimal }
|
||||
ul li { padding-bottom: 5px; margin: 0 }
|
||||
ol { font-family: monospace; white-space: pre; list-style-position: inside; margin: 0; padding: 10px 0 }
|
||||
ol li { margin: -5px; padding: 0 }
|
||||
ol .selected { font-weight: bold; background-color: #ffd; padding: 2px 0 }
|
||||
table.vars { padding: 0; margin: 0; border: 1px solid #999; background-color: #fff; }
|
||||
table.vars th { padding: 2px; background-color: #ddd; font-weight: bold }
|
||||
table.vars td { padding: 2px; font-family: monospace; white-space: pre }
|
||||
p.error { padding: 10px; background-color: #f00; font-weight: bold; text-align: center; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; }
|
||||
p.error a { color: #fff }
|
||||
#main { padding: 20px 25px; margin: 0; margin-bottom: 20px; border: 1px solid #ddd; background-color: #fff; text-align:left; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; min-width: 770px; max-width: 770px }
|
||||
#message { padding: 20px 25px; margin: 0; margin-bottom: 5px; border: 1px solid #ddd; text-align:left; background-color: #c8e8f3; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; min-width: 770px; max-width: 770px }
|
||||
#content { border: 1px solid #ddd; margin-top: 10px; padding: 7px; overflow: auto; }
|
||||
a.file_link { text-decoration: none; }
|
||||
a.file_link:hover { text-decoration: underline; }
|
||||
.code { overflow: auto; }
|
||||
img { vertical-align: middle; }
|
||||
a img { border: 0; }
|
||||
.error { background-color: #f66; padding: 1px 3px; color: #111; }
|
||||
<?php echo $view->render('FrameworkBundle:Exception:styles') ?>
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function toggle(id)
|
||||
@ -44,8 +20,8 @@
|
||||
<img src="data:image/png;base64,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" />
|
||||
</div>
|
||||
<div style="float: left; width: 600px">
|
||||
<h2><?php echo $code ?> <?php echo $text ?> - <?php echo $name ?></h2>
|
||||
<h1><?php echo str_replace("\n", '<br />', htmlspecialchars($message, ENT_QUOTES, $charset)) ?></h1>
|
||||
<h2><?php echo $manager->getStatusCode() ?> <?php echo $manager->getStatusText() ?> - <?php echo $manager->getName() ?></h2>
|
||||
<h1><?php echo str_replace("\n", '<br />', htmlspecialchars($manager->getMessage(), ENT_QUOTES, $view->getCharset())) ?></h1>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
@ -54,30 +30,23 @@
|
||||
<div id="main">
|
||||
<h3>
|
||||
Logs <a href="#" onclick="toggle('logs'); return false;">...</a>
|
||||
<?php if ($errors): ?>
|
||||
<span class="error"><?php echo $errors ?> errors</span>
|
||||
<?php if ($manager->countErrors()): ?>
|
||||
<span class="error"><?php echo $manager->countErrors() ?> errors</span>
|
||||
<?php endif; ?>
|
||||
</h3>
|
||||
|
||||
<div id="logs" style="display: none">
|
||||
<ul>
|
||||
<?php foreach ($logs as $log): ?>
|
||||
<li<?php if ('ERR' === $log['priorityName']): ?> class="error"<?php endif; ?>>
|
||||
<?php echo $log['priorityName'] ?>:
|
||||
<?php echo $log['message'] ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:logs', array('logs' => $manager->getLogs())) ?>
|
||||
</div>
|
||||
|
||||
<h3>Stack Trace</h3>
|
||||
|
||||
<ul><li><?php echo implode('</li><li>', $traces) ?></li></ul>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:traces', array('traces' => $manager->getTraces())) ?>
|
||||
|
||||
<h3>Content of the Output <a href="#" onclick="toggle('content'); return false;">...</a></h3>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
<?php echo $currentContent ?>
|
||||
<?php echo $manager->getCurrentContent() ?>
|
||||
</div>
|
||||
|
||||
<div style="clear: both"></div>
|
@ -1 +1 @@
|
||||
<?php include sfException::getTemplatePathForError('xml', true) ?>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:exception.xml', array('manager' => $manager)) ?>
|
||||
|
@ -1,13 +1,14 @@
|
||||
[exception] <?php echo $code.' | '.$text.' | '.$name ?>
|
||||
[exception] <?php echo $manager->getStatusCode().' | '.$manager->getStatusText().' | '.$manager->getName() ?>
|
||||
|
||||
[message] <?php echo $message ?>
|
||||
[message] <?php echo $manager->getMessage() ?>
|
||||
|
||||
<?php if (isset($traces) && count($traces) > 0): ?>
|
||||
<?php if (count($manager->getTraces())): ?>
|
||||
[stack trace]
|
||||
<?php foreach ($traces as $line): ?>
|
||||
<?php echo $line ?>
|
||||
<?php foreach ($manager->getTraces() as $i => $trace): ?>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:trace.txt', array('i' => $i, 'trace' => $trace)) ?>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php endif; ?>
|
||||
[symfony] v. <?php echo \Symfony\Framework\Kernel::VERSION ?> (symfony-project.org)
|
||||
[PHP] v. <?php echo PHP_VERSION ?>
|
||||
|
@ -1,11 +1,14 @@
|
||||
<?php echo sprintf('<?xml version="1.0" encoding="%s" ?>', $charset)."\n" ?>
|
||||
<error code="<?php echo $code ?>" message="<?php echo $text ?>">
|
||||
<?php echo sprintf('<?xml version="1.0" encoding="%s" ?>', $view->getCharset())."\n" ?>
|
||||
<error code="<?php echo $manager->getStatusCode() ?>" message="<?php echo $manager->getStatusText() ?>">
|
||||
<debug>
|
||||
<name><?php echo $name ?></name>
|
||||
<message><?php echo htmlspecialchars($message, ENT_QUOTES, $charset) ?></message>
|
||||
<name><?php echo $manager->getName() ?></name>
|
||||
<message><?php echo htmlspecialchars($manager->getMessage(), ENT_QUOTES, $view->getCharset()) ?></message>
|
||||
<traces>
|
||||
<?php foreach ($traces as $trace): ?>
|
||||
<trace><?php echo $trace ?></trace>
|
||||
<?php foreach ($manager->getTraces() as $i => $trace): ?>
|
||||
<trace>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:trace.txt', array('i' => $i, 'trace' => $trace)) ?>
|
||||
|
||||
</trace>
|
||||
<?php endforeach; ?>
|
||||
</traces>
|
||||
</debug>
|
||||
|
@ -0,0 +1,8 @@
|
||||
<ul>
|
||||
<?php foreach ($logs as $log): ?>
|
||||
<li<?php if ('ERR' === $log['priorityName']): ?> class="error"<?php endif; ?>>
|
||||
<?php echo $log['priorityName'] ?>:
|
||||
<?php echo $log['message'] ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
@ -0,0 +1,25 @@
|
||||
body { margin: 0; padding: 0; margin-top: 30px; background-color: #eee }
|
||||
body, td, th { font: 11px Verdana, Arial, sans-serif; color: #333 }
|
||||
a { color: #333 }
|
||||
h1 { margin: 0; margin-top: 4px; font-weight: normal; font-size: 170%; letter-spacing: -0.03em; }
|
||||
h2 { margin: 0; padding: 0; font-size: 90%; font-weight: normal; letter-spacing: -0.02em; }
|
||||
h3 { margin: 0; padding: 0; margin-bottom: 10px; font-size: 110% }
|
||||
ul { padding-left: 20px; list-style: decimal }
|
||||
ul li { padding-bottom: 5px; margin: 0 }
|
||||
ol { font-family: monospace; white-space: pre; list-style-position: inside; margin: 0; padding: 10px 0 }
|
||||
ol li { margin: -5px; padding: 0 }
|
||||
ol .selected { font-weight: bold; background-color: #ffd; padding: 2px 0 }
|
||||
table.vars { padding: 0; margin: 0; border: 1px solid #999; background-color: #fff; }
|
||||
table.vars th { padding: 2px; background-color: #ddd; font-weight: bold }
|
||||
table.vars td { padding: 2px; font-family: monospace; white-space: pre }
|
||||
p.error { padding: 10px; background-color: #f00; font-weight: bold; text-align: center; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; }
|
||||
p.error a { color: #fff }
|
||||
#main { padding: 20px 25px; margin: 0; margin-bottom: 20px; border: 1px solid #ddd; background-color: #fff; text-align:left; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; min-width: 770px; max-width: 770px }
|
||||
#message { padding: 20px 25px; margin: 0; margin-bottom: 5px; border: 1px solid #ddd; text-align:left; background-color: #c8e8f3; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; min-width: 770px; max-width: 770px }
|
||||
#content { border: 1px solid #ddd; margin-top: 10px; padding: 7px; overflow: auto; }
|
||||
a.file_link { text-decoration: none; }
|
||||
a.file_link:hover { text-decoration: underline; }
|
||||
.code { overflow: auto; }
|
||||
img { vertical-align: middle; }
|
||||
a img { border: 0; }
|
||||
.error { background-color: #f66; padding: 1px 3px; color: #111; }
|
@ -0,0 +1,10 @@
|
||||
<?php if ($trace['function']): ?>
|
||||
at <strong><?php echo $trace['class'] ?><?php echo $trace['type'] ?><?php echo $trace['function'] ?></strong>(<?php echo $view->code->formatArgs($trace['args']) ?>)<br />
|
||||
<?php endif; ?>
|
||||
<?php if ($trace['file'] && $trace['line']): ?>
|
||||
in <em><?php echo $view->code->formatFile($trace['file'], $trace['line']) ?></em> line <?php echo $trace['line'] ?>
|
||||
<a href="#" onclick="toggle('trace_<?php echo $i ?>'); return false;">...</a><br />
|
||||
<ul class="code" id="trace_<?php echo $i ?>" style="display: <?php echo 0 === $i ? 'block' : 'none' ?>">
|
||||
<?php echo $view->code->fileExcerpt($trace['file'], $trace['line']) ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
@ -0,0 +1,8 @@
|
||||
<?php if ($trace['function']): ?>
|
||||
at <?php echo $trace['class'].$trace['type'].$trace['function'] ?>(<?php echo $view->code->formatArgs($trace['args']) ?>)
|
||||
<?php else: ?>
|
||||
at n/a
|
||||
<?php endif; ?>
|
||||
<?php if ($trace['file'] && $trace['line']): ?>
|
||||
in <?php echo $trace['file'] ?> line <?php echo $trace['line'] ?>
|
||||
<?php endif; ?>
|
@ -0,0 +1,7 @@
|
||||
<ul>
|
||||
<?php foreach ($traces as $i => $trace): ?>
|
||||
<li>
|
||||
<?php echo $view->render('FrameworkBundle:Exception:trace', array('i' => $i, 'trace' => $trace)) ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
|
||||
|
||||
use Symfony\Components\Templating\Helper\Helper;
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CodeHelper.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class CodeHelper extends Helper
|
||||
{
|
||||
protected $fileLinkFormat;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $fileLinkFormat The format for links to source files
|
||||
*/
|
||||
public function __construct($fileLinkFormat)
|
||||
{
|
||||
$this->fileLinkFormat = null !== $fileLinkFormat ? $fileLinkFormat : ini_get('xdebug.file_link_format');
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an array as a string.
|
||||
*
|
||||
* @param array $args The argument array
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formatArgs($args)
|
||||
{
|
||||
$result = array();
|
||||
foreach ($args as $key => $value) {
|
||||
if (is_object($value)) {
|
||||
$formattedValue = sprintf("object('%s')", get_class($value));
|
||||
} elseif (is_array($value)) {
|
||||
$formattedValue = sprintf("array(%s)", $this->formatArgs($value));
|
||||
} elseif (is_string($value)) {
|
||||
$formattedValue = sprintf("'%s'", $value);
|
||||
} elseif (null === $value) {
|
||||
$formattedValue = 'null';
|
||||
} else {
|
||||
$formattedValue = $value;
|
||||
}
|
||||
|
||||
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an excerpt of a code file around the given line number.
|
||||
*
|
||||
* @param string $file A file path
|
||||
* @param int $line The selected line number
|
||||
*
|
||||
* @return string An HTML string
|
||||
*/
|
||||
public function fileExcerpt($file, $line)
|
||||
{
|
||||
if (is_readable($file)) {
|
||||
$content = preg_split('#<br />#', highlight_file($file, true));
|
||||
|
||||
$lines = array();
|
||||
for ($i = max($line - 3, 1), $max = min($line + 3, count($content)); $i <= $max; $i++) {
|
||||
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'>'.$content[$i - 1].'</li>';
|
||||
}
|
||||
|
||||
return '<ol start="'.max($line - 3, 1).'">'.implode("\n", $lines).'</ol>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a file path.
|
||||
*
|
||||
* @param string $file An absolute file path
|
||||
* @param integer $line The line number
|
||||
* @param string $format The output format (txt or html)
|
||||
* @param string $text Use this text for the link rather than the file path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formatFile($file, $line)
|
||||
{
|
||||
if (!$this->fileLinkFormat) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
$link = strtr($this->fileLinkFormat, array('%f' => $file, '%l' => $line));
|
||||
|
||||
return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', $link, $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the canonical name of this helper.
|
||||
*
|
||||
* @return string The canonical name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'code';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user