[FrameworkBundle] added support for previous exceptions in the exception pages

This commit is contained in:
Fabien Potencier 2010-08-24 12:52:55 +02:00
parent 789a02d56d
commit ec8500bd64
18 changed files with 250 additions and 92 deletions

View File

@ -32,9 +32,18 @@ class ExceptionController extends Controller
{
$this['request']->setRequestFormat($manager->getFormat());
$currentContent = '';
while (false !== $content = ob_get_clean()) {
$currentContent .= $content;
}
$response = $this->render(
'FrameworkBundle:Exception:'.($this['kernel']->isDebug() ? 'exception' : 'error'),
array('manager' => $manager)
array(
'manager' => $manager,
'managers' => $manager->getLinkedManagers(),
'currentContent' => $currentContent,
)
);
$response->setStatusCode($manager->getStatusCode());

View File

@ -27,18 +27,23 @@ class ExceptionManager
protected $exception;
protected $request;
protected $logger;
protected $currentContent;
public function __construct(\Exception $exception, Request $request, DebugLoggerInterface $logger = null)
{
$this->exception = $exception;
$this->request = $request;
$this->logger = $logger;
}
$this->currentContent = '';
while (false !== $content = ob_get_clean()) {
$this->currentContent .= $content;
public function getLinkedManagers()
{
$managers = array();
$e = $this->exception;
while ($e = $e->getPrevious()) {
$managers[] = new $this($e, $this->request);
}
return $managers;
}
public function getException()
@ -46,11 +51,6 @@ class ExceptionManager
return $this->exception;
}
public function getCurrentContent()
{
return $this->currentContent;
}
public function getLogger()
{
return $this->logger;
@ -126,13 +126,23 @@ class ExceptionManager
'args' => array(),
);
foreach ($this->exception->getTrace() as $entry) {
$class = '';
$namespace = '';
if (isset($entry['class'])) {
$parts = explode('\\', $entry['class']);
$class = array_pop($parts);
$namespace = implode('\\', $parts);
}
$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(),
'namespace' => $namespace,
'short_class' => $class,
'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(),
);
}

View File

@ -92,6 +92,7 @@
<service id="templating.helper.code" class="%templating.helper.code.class%">
<tag name="templating.helper" alias="code" />
<argument>%debug.file_link_format%</argument>
<argument>%kernel.root_dir%</argument>
</service>
<service id="templating.loader" alias="templating.loader.filesystem" />

View File

@ -1,9 +1,25 @@
<?php echo json_encode(array(
<?php
$vars = array(
'error' => array(
'code' => $manager->getStatusCode(),
'message' => $manager->getMessage(),
'debug' => array(
'message' => $manager->getName(),
'exception' => array(
'name' => $manager->getName(),
'message' => $manager->getMessage(),
'traces' => $manager->getTraces(),
),
))) ?>
));
if (count($managers)) {
$vars['exceptions'] = array();
foreach ($managers as $i => $previous) {
$vars['exceptions'][] = array(
'name' => $previous->getName(),
'message' => $previous->getMessage(),
'traces' => $previous->getTraces(),
);
}
}
echo json_encode($vars);

View File

@ -7,10 +7,21 @@
<?php echo $view->render('FrameworkBundle:Exception:styles') ?>
</style>
<script type="text/javascript">
function toggle(id)
{
el = document.getElementById(id); el.style.display = el.style.display == 'none' ? 'block' : 'none';
}
function toggle(id, clazz) {
el = document.getElementById(id);
current = el.style.display
if (clazz) {
var tags = document.getElementsByTagName('*');
for (i = 0; i < tags.length; i++) {
if (tags[i].className == clazz) {
tags[i].style.display = 'none';
}
}
}
el.style.display = current == 'none' ? 'block' : 'none';
}
</script>
</head>
<body>
@ -20,33 +31,50 @@
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAuCAYAAABeUotNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACoJJREFUeNrUWXuMFVcd/mbu+7nLlmVZXgV5FJe6lNhu2kjJQtm0iTQh0QhKpaCNtkQxlNAUg4lSRRKalERLU6m2EpWo/AG1UVqwYEKplhRwiYFCtwUKWbLsLuy9e59zZ8bvzL0z9+zs3N2F6h+d5HfPzNzz+M7v/TujmKaJz8LlFz+KotzW4N8BLRy5hJO0s52nA+P5OmrNCWTY9JDOlIC32eftlUDX7QJVBEdvBegfgCYDWMeFv+MDYhOiUf+4ZDISC4UQDAQQ4FymrkMn5fN5ZAsFXM9ksn2aZnAjfRz7Eqf51Srgxv8F6KtAfQTYzoVWT4rHlWnNzeFkYyNAIBgYALLZ8n2pBKUsJoDALeImTMPAjXQal1KpXE+pZPDfX6aArd/lyP8ZUIr4qyrwSnMiEZo9e3Y4GI/D/OQTmNeuQSHX1LKoHZIv0yYCNjkO0SiyuRzO37yZ7dX1DNVi5WqqxacC+ifAR3Ht8qnqqvlz58bqJ02CfuECzCtXoJJDAqBNigdY20yNyr1oDaEaYqORCPoGB/EfqgXXeOHrwI+U6pCxAyXIICf4S104/KUvtLXFfOSC3tkJpVh0wPlEG4tB7eiAev/9UGbOBOrquJxpqYPS1QXz+HEYhw/D5HjDBivI54OZSKDADf87lcrkTPMA51v9NUAfM9AKJ/82PhZb2LJwYcT46CPoH35YBlYh/733wv/001CWLIFK7thzyHPZrs+k/hqHDsHYsQMGN2uDFYhMqoLu96OTYFOm+Wca2doxA91LRU+GQmtaFy+O6efOwbh0yQHpnzwZgeeeg3/5ciiqao2VyX2J+R2iJzD27UNpyxboPT1V7obDKJHDZzKZdMY0t32DRjsqUBrOspCi/P6+9vakefkydHLTBhloa0N4zx4oEyZAlUDa9z3vvYcLe/dCp4GNv+cefP6JJ6AQgEHxyoAN6rj22GPQT5+2uGqBpWcoco5TuVyavqODBvavmkAp8jgHdrXOmzchSt3TTpxwdDG4bBlCL78Mlbu3gcmtoWn466OPopStepsFzzyD6XxngauAdVr209asgSZUwlYDzj1A93ZO0z6eCMxZTGdnz6XKqPn2p02JRDJ+550onDzpvPeRO6Fdu6Bw125R21To7x8CUlyDlIhXX4tD1Gu/2HhLS1VN6Ifj1NdxQGM3sEGeS5Uijgh/a6cuWBAunDkDs1TejNLQgOCrdPeSwchGY7dBWrD7CtANufsNAUsPEXjtNaAy1jI+rjvF74+zx7OUcMSLoxsn1teH/BxUpDO3/WBowwao9J8jOmMuLICGhGuSrsTUqRgtl1BmzIBv3boqVwnUz/6cKUR1+NYQoGY54H276a67QgU6dBukOm0aAo8/PuZ4HJsyZchzkiDGcgWeeooZRFM1klGP71DVGDF9fwhQiv0+n6IEo9TNIl2RHR6Ca+nSgsFRF7L9ZUzmPLcerwCXU0nPtFLo6+rV1XBLoHERwYDJdJXTZY52NDQ2RnSGNIMKbQ/wP/xwzUUcZy61seZm5/8oOaSKZMTVz2usZbBirfLLshvjbbzsutodoPxZykwoqNEJ20PVuXOhkMNek9eiGIOBo58cW6ufF1h13jwo1GlTSmRixErxL5aNaZYwhBLjs93J19o6Ivdk0MI3CopIHI1Tv+33ssMfaR6VazoJDJ+DwkcDrQ5Q/jleuBI9k3GAWrsbgXteFJWB3uJ465I5yne+8n2TU4rwCqt0tCK62OkYGJns3Qr3IrdeRiGeg/S5Ko3PYIYVo+htTrq5X1MVRPoniV4pt9EhftQsW5lDYrGROCCL1VlcGNHEiY6rksOmWwW8dF4YspwKVlihVIs7IF/StLAoGxygDImjcdHNUdFXiL9w4wYC1PlagGpx1+C4IcwqT52VRX9Dy2SaFeaGlT+hiUxe1h8xUGT1qloTpGgj5GiRtZHo6071RvIa1prnz1c5yvmK5fc9MtAL+YGB5pjgQmU3BaZsIkkQGY18CQBeiYYNVlh+idl8LcuuRXoqheKpU876ImAUBcdZbssO/+/pnh7NxzzT2RE9QOHYMU/l99JV+75p0SJMX7Fi2PvR5ikcOQKTdiHraA7IENs/ZKCHU729GZWJhSms1u544MCoIN2A/ZSK4KqXsdUCLN7l9+8fInazDNTk82EHaBfwT7JZzzB/DAlHXRmQff11aKIUcS3qtbj9nO/txQDrK/dmvDZlk0aR51kAOtZOO8iLftRPZvofO0B/XP5/T9/58xoL92ppy0nS27ePylG7vU69Ps7y48T69Tj34ovDs3ov8Ys1tm2zIpEMNGUYWeL4xbB8lB129Pf3Z0usd/zMghzxHz2KLOukkfTSbrtZVpgMGuLqfvNN6Lz36iePz7z0kmW4DkjWWCW+H6Q9M297ZRjQb3JuUTZ1nzxZjLH0gCjKKoNvbt2KwjvveC4o3yeZyDhJCSUDUUuNoKN5biz1/PPVAk/oJn35DV0XRrSTNf6gZ3HHCjRJ5F3T588fH2BIHXz/fSssqJWDhjt27kR46dJh5Yhzz7l6330Xxb4+ND30EHzRaM0UL//GG7i5aZNVsTohk2lhniX19VLpKivRWcyG8zXL5d8AK2KqunvWkiWJPI2icPFi9ciGHKrfuBGJJ5+0uDVSaVIzihFIihtOU4ftsGuD1DmuO59PXwZWPVs+j8pXCtRhQEXCEibY3XWRyPIZ7e2RTGcnilevDjlfCs6Zg/rNmxFub7+lM84c9VaIWhNeQU4+CBKU4LVsNtNjmr9l/fEzEXMqQHOWVriAijAUnkkV2wLsa0gmW6c88EA498EHyJOz7oOw0N13I/LII4h2dCBA8F6XdvYscm+9hezBg5arkwHaZbNCvewZHMz3GsbxHwDfK5bB5WWSgfpsoII+BzT8kC5rXDQ6d2pbW1hnUp1hGW2ff9pbs+9VOno/UzsRNMSzwZCosf4SLVyne1ZL1VGTSeg0ruvpdK7fNE+SOZv6gbTESRtoVgbql4EKYqGf/Anw83pVXTSlpSUcbWxEltwtdndbhuM+Dx3plNWU0kmVRuajceYYpq9nMoWrwEGCfKFUzpTcIIcBVd1AbdoMfKUF2JCorw80zp7t91FUBdb+xWvXLL/pBug+H7XeUQeF5xAANSY7/QMDWq5UKh4jwN3AEbeoRwJqVcgSwJAMdgHQvAZY3wA8mKir89U3N/tCzOhF8iJqLT2bLWdbul49ESE4hbmDqEaFqAtUg1Q6reU0zSQXj+4Cfk0L76sYTsEFzn4WHy10r2PHkAtoSKYHgWlfBlayOlqqcmA8Hg9GEgl/gGAEp63ygWAFCc5p9JO5bLaUKxQ0bkG7yCTjj8D+s+U8U4ApSkBlwKIdrOWenMMLF8ig1AoK8M8QAdPu8UVWXwv4PJlKnuBMQeH6BShGmwGudPUKcLoTOHWIeS/1UMRYmYoSWLvN2W5pLGf4igtosLIBmfwVb+H3OM6Hq6owygeGFodK8AZcqJQepdv5KqJUgMhg/RL57ON821O5xsvfGnQJqE3FiqiLMgc/9QcxiYP+Cmj5aF+t8QVHPrbXXEDH9I3zdoDW4jo8PjWZLhW4/QU+Kx9t/yvAAAhp2995XB6rAAAAAElFTkSuQmCC" />
</div>
<div style="float: left; width: 600px">
<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>
<h2><strong><?php echo $manager->getStatusCode() ?></strong> <?php echo $manager->getStatusText() ?> - <?php echo $manager->getName() ?></h2>
<?php if (count($managers)): ?>
<div class="linked"><span><strong><?php echo count($managers) ?></strong> linked Exception<?php if (count($managers) > 1): ?>s<?php endif; ?>:</span>
<ul>
<?php foreach ($managers as $i => $previous): ?>
<li>
<?php echo $previous->getName() ?> <a href="#traces_link_<?php echo $i + 1 ?>" onclick="toggle('traces_<?php echo $i + 1 ?>', 'traces');">&raquo;</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
</div>
<div style="clear: both"></div>
</div>
<div id="main">
<?php echo $view->render('FrameworkBundle:Exception:traces', array('manager' => $manager, 'position' => 0, 'count' => count($managers))) ?>
<?php foreach ($managers as $i => $previous): ?>
<?php echo $view->render('FrameworkBundle:Exception:traces', array('manager' => $previous, 'position' => $i + 1, 'count' => count($managers))) ?>
<?php endforeach; ?>
<div class="block">
<h3>
Logs <a href="#" onclick="toggle('logs'); return false;">...</a>
<?php if ($manager->countErrors()): ?>
<span class="error"><?php echo $manager->countErrors() ?> errors</span>
<span class="error"><?php echo $manager->countErrors() ?> error<?php if ($manager->countErrors() > 1): ?>s<?php endif; ?></span>
<?php endif; ?>
Logs <a href="#" onclick="toggle('logs'); return false;">&raquo;</a>
</h3>
<div id="logs" style="display: none">
<?php echo $view->render('FrameworkBundle:Exception:logs', array('logs' => $manager->getLogs())) ?>
</div>
<h3>Stack Trace</h3>
</div>
<?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 class="block">
<h3>Content of the Output <a href="#" onclick="toggle('content'); return false;">&raquo;</a></h3>
<div id="content" style="display: none">
<?php echo $manager->getCurrentContent() ?>
<?php echo $currentContent ?>
</div>
<div style="clear: both"></div>

View File

@ -1,14 +1,19 @@
[exception] <?php echo $manager->getStatusCode().' | '.$manager->getStatusText().' | '.$manager->getName() ?>
[exception] <?php echo $manager->getStatusCode().' | '.$manager->getStatusText().' | '.$manager->getName() ?>
[message] <?php echo $manager->getMessage() ?>
[message] <?php echo $manager->getMessage() ?>
<?php if (count($manager->getTraces())): ?>
[stack trace]
<?php foreach ($manager->getTraces() as $i => $trace): ?>
<?php echo $view->render('FrameworkBundle:Exception:trace.txt', array('i' => $i, 'trace' => $trace)) ?>
<?php endforeach; ?>
<?php echo $view->render('FrameworkBundle:Exception:traces', array('manager' => $manager, 'position' => 0, 'count' => count($managers))) ?>
<?php endif; ?>
[symfony] v. <?php echo \Symfony\Framework\Kernel::VERSION ?> (symfony-project.org)
[PHP] v. <?php echo PHP_VERSION ?>
<?php if (count($managers)): ?>
<?php foreach ($managers as $i => $previous): ?>
[linked exception] <?php echo $previous->getName() ?>: <?php echo $previous->getMessage() ?>
<?php echo $view->render('FrameworkBundle:Exception:traces', array('manager' => $previous, 'position' => $i + 1, 'count' => count($managers))) ?>
<?php endforeach; ?>
<?php endif; ?>
[symfony] v. <?php echo \Symfony\Framework\Kernel::VERSION ?> (symfony-project.org)
[PHP] v. <?php echo PHP_VERSION ?>

View File

@ -1,15 +1,13 @@
<?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 $manager->getName() ?></name>
<message><?php echo htmlspecialchars($manager->getMessage(), ENT_QUOTES, $view->getCharset()) ?></message>
<traces>
<?php foreach ($manager->getTraces() as $i => $trace): ?>
<trace>
<?php echo $view->render('FrameworkBundle:Exception:trace.txt', array('i' => $i, 'trace' => $trace)) ?>
</trace>
<exception class="<?php echo $manager->getName() ?>" message="<?php echo $manager->getMessage() ?>">
<?php echo $view->render('FrameworkBundle:Exception:traces', array('manager' => $manager, 'position' => 0, 'count' => count($managers))) ?>
</exception>
<?php if (count($managers)): ?>
<?php foreach ($managers as $i => $previous): ?>
<exception class="<?php echo $previous->getName() ?>" message="<?php echo $previous->getMessage() ?>">
<?php echo $view->render('FrameworkBundle:Exception:traces', array('manager' => $previous, 'position' => $i + 1, 'count' => count($managers))) ?>
</exception>
<?php endforeach; ?>
</traces>
</debug>
<?php endif; ?>
</error>

View File

@ -1,25 +1,41 @@
body { margin: 0; padding: 0; margin-top: 30px; background-color: #eee }
body, td, th { font: 11px Verdana, Arial, sans-serif; color: #333 }
/*
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 3.1.2
build: 56
*/
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
/*
Symfony stylesheet
*/
html { background: #eee }
body { font: 11px Verdana, Arial, sans-serif; color: #333 }
strong { font-weight: bold }
em { font-style: italic }
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 }
abbr { border-bottom: 1px dotted #000000; cursor: help }
h1 { font-size: 170%; letter-spacing: -0.03em; }
h2 { margin-top: 4px; font-size: 90%; letter-spacing: -0.02em; }
h3 { font-size: 130%; font-weight: bold; letter-spacing: -0.02em; }
h3 span { float: right; font-size: 80%; background: #eee; color: #333; padding: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
ul { padding-left: 20px }
ul li { padding-bottom: 5px; list-style: decimal }
ol { font-family: monospace; white-space: pre; padding: 10px 0 }
ol li { margin: -5px; list-style: decimal; list-style-position: inside }
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 }
.block { padding: 20px 25px; margin-bottom: 10px; 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 }
.traces { display: none; margin-top: 10px }
#message { margin-top: 30px; margin-bottom: 10px; padding: 20px 25px; 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; }
.error { background-color: #f66 }
.linked ul, .linked li { padding-left: 0; display: inline }
.linked li { padding-right: 7px }
#logs { margin-top: 10px }

View File

@ -1,10 +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 />
at <strong><abbr title="<?php echo $trace['class'] ?>"><?php echo $trace['short_class'] ?></abbr><?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' ?>">
<a href="#" onclick="toggle('trace_<?php echo $prefix.'_'.$i ?>'); return false;">&raquo;</a><br />
<ul class="code" id="trace_<?php echo $prefix.'_'.$i ?>" style="display: <?php echo 0 === $i ? 'block' : 'none' ?>">
<?php echo $view['code']->fileExcerpt($trace['file'], $trace['line']) ?>
</ul>
<?php endif; ?>

View File

@ -1,5 +1,5 @@
<?php if ($trace['function']): ?>
at <?php echo $trace['class'].$trace['type'].$trace['function'] ?>(<?php echo $view['code']->formatArgs($trace['args']) ?>)
at <?php echo $trace['class'].$trace['type'].$trace['function'] ?>(<?php echo $view['code']->formatArgsAsText($trace['args']) ?>)
<?php else: ?>
at n/a
<?php endif; ?>

View File

@ -1,7 +1,20 @@
<ul>
<?php foreach ($traces as $i => $trace): ?>
<li>
<?php echo $view->render('FrameworkBundle:Exception:trace', array('i' => $i, 'trace' => $trace)) ?>
</li>
<?php endforeach; ?>
</ul>
<div class="block">
<?php if ($count > 0): ?>
<h3>
<span><?php echo $count - $position + 1 ?>/<?php echo $count + 1 ?></span>
<?php echo $manager->getName() ?>: <?php echo str_replace("\n", '<br />', htmlspecialchars($manager->getMessage(), ENT_QUOTES, $view->getCharset())) ?>
<a href="#" onclick="toggle('traces_<?php echo $position ?>', 'traces'); return false;">&raquo;</a><br />
</h3>
<?php else: ?>
<h3>Stack Trace</h3>
<?php endif; ?>
<a id="traces_link_<?php echo $position ?>"></a>
<ul class="traces" id="traces_<?php echo $position ?>" style="display: <?php echo 0 === $position ? 'block' : 'none' ?>">
<?php foreach ($manager->getTraces() as $i => $trace): ?>
<li>
<?php echo $view->render('FrameworkBundle:Exception:trace', array('prefix' => $position, 'i' => $i, 'trace' => $trace)) ?>
</li>
<?php endforeach; ?>
</ul>
</div>

View File

@ -0,0 +1,6 @@
<?php if (count($manager->getTraces())): ?>
<?php foreach ($manager->getTraces() as $i => $trace): ?>
<?php echo $view->render('FrameworkBundle:Exception:trace.txt', array('i' => $i, 'trace' => $trace)) ?>
<?php endforeach; ?>
<?php endif;?>

View File

@ -0,0 +1,8 @@
<traces>
<?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>

View File

@ -21,15 +21,51 @@ use Symfony\Component\Templating\Helper\Helper;
class CodeHelper extends Helper
{
protected $fileLinkFormat;
protected $rootDir;
/**
* Constructor.
*
* @param string $fileLinkFormat The format for links to source files
* @param string $rootDir The project root directory
*/
public function __construct($fileLinkFormat)
public function __construct($fileLinkFormat, $rootDir)
{
$this->fileLinkFormat = null !== $fileLinkFormat ? $fileLinkFormat : ini_get('xdebug.file_link_format');
$this->rootDir = str_replace('\\', '/', $rootDir).'/';
}
/**
* Formats an array as a string.
*
* @param array $args The argument array
*
* @return string
*/
public function formatArgsAsText($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';
} elseif (false === $value) {
$formattedValue = 'false';
} elseif (true === $value) {
$formattedValue = 'true';
} else {
$formattedValue = $value;
}
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
}
return implode(', ', $result);
}
/**
@ -44,13 +80,20 @@ class CodeHelper extends Helper
$result = array();
foreach ($args as $key => $value) {
if (is_object($value)) {
$formattedValue = sprintf("object('%s')", get_class($value));
$class = get_class($value);
$parts = explode('\\', $class);
$short = array_pop($parts);
$formattedValue = sprintf("<em>object</em>(<abbr title=\"%s\">%s</abbr>)", $class, $short);
} elseif (is_array($value)) {
$formattedValue = sprintf("array(%s)", $this->formatArgs($value));
$formattedValue = sprintf("<em>array</em>(%s)", $this->formatArgs($value));
} elseif (is_string($value)) {
$formattedValue = sprintf("'%s'", $value);
} elseif (null === $value) {
$formattedValue = 'null';
$formattedValue = '<em>null</em>';
} elseif (false === $value) {
$formattedValue = '<em>false</em>';
} elseif (true === $value) {
$formattedValue = '<em>true</em>';
} else {
$formattedValue = $value;
}
@ -95,13 +138,18 @@ class CodeHelper extends Helper
*/
public function formatFile($file, $line)
{
if (0 === strpos($file, $this->rootDir)) {
$file = str_replace($this->rootDir, '', str_replace('\\', '/', $file));
$file = sprintf('<abbr title="%s">kernel.root_dir</abbr>/%s', $this->rootDir, $file);
}
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);
return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', $link, $this->rootDir, $file);
}
/**

View File

@ -75,7 +75,7 @@ class Parser
} catch (\Exception $e) {
$class = get_class($e);
throw new $class(sprintf('%s at %s -> %s', $e->getMessage(), implode($stream->getUsed(), ''), $stream->peek()));
throw new $class(sprintf('%s at %s -> %s', $e->getMessage(), implode($stream->getUsed(), ''), $stream->peek()), 0, $e);
}
}

View File

@ -176,7 +176,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
return parent::get($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
} catch (\InvalidArgumentException $e) {
if (isset($this->loading[$id])) {
throw new \LogicException(sprintf('The service "%s" has a circular reference to itself.', $id));
throw new \LogicException(sprintf('The service "%s" has a circular reference to itself.', $id), 0, $e);
}
if (!$this->hasDefinition($id) && isset($this->aliases[$id])) {

View File

@ -108,7 +108,7 @@ class PdoSessionStorage extends NativeSessionStorage
$stmt->bindParam(1, $id, \PDO::PARAM_STR);
$stmt->execute();
} catch (\PDOException $e) {
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data. Message: %s', $e->getMessage()));
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
}
return true;
@ -135,7 +135,7 @@ class PdoSessionStorage extends NativeSessionStorage
try {
$this->db->query($sql);
} catch (\PDOException $e) {
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data. Message: %s', $e->getMessage()));
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
}
return true;
@ -184,7 +184,7 @@ class PdoSessionStorage extends NativeSessionStorage
return '';
}
} catch (\PDOException $e) {
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data. Message: %s', $e->getMessage()));
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
}
}
@ -214,7 +214,7 @@ class PdoSessionStorage extends NativeSessionStorage
$stmt->bindParam(2, $id, \PDO::PARAM_STR);
$stmt->execute();
} catch (\PDOException $e) {
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data. Message: %s', $e->getMessage()));
throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
}
return true;

View File

@ -89,7 +89,7 @@ class Yaml
try {
$ret = $yaml->parse($input);
} catch (\Exception $e) {
throw new \InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()));
throw new \InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()), 0, $e);
}
return $ret;