From c25bbbcedc4ab3d64e3c82896ba2ac766397d34c Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 29 Nov 2015 15:44:28 +0100 Subject: [PATCH 01/10] Added support for printing frame args in the framestack. --- src/Whoops/Resources/css/whoops.base.css | 9 ++ .../Resources/views/env_details.html.php | 2 +- .../Resources/views/frame_list.html.php | 3 +- src/Whoops/Util/TemplateHelper.php | 96 ++++++++++++++----- 4 files changed, 84 insertions(+), 26 deletions(-) diff --git a/src/Whoops/Resources/css/whoops.base.css b/src/Whoops/Resources/css/whoops.base.css index a1695ce..b0a2471 100644 --- a/src/Whoops/Resources/css/whoops.base.css +++ b/src/Whoops/Resources/css/whoops.base.css @@ -136,6 +136,15 @@ header { font-size: 14px; } + .frame-arg { + margin-left: 20px; + display: block; + } + + .frame-arg-separated .sf-dump::after { + content: ','; + } + .frame-index { font-size: 11px; color: #a29d9d; diff --git a/src/Whoops/Resources/views/env_details.html.php b/src/Whoops/Resources/views/env_details.html.php index fbed55d..8db1493 100644 --- a/src/Whoops/Resources/views/env_details.html.php +++ b/src/Whoops/Resources/views/env_details.html.php @@ -17,7 +17,7 @@ $value): ?> escape($k) ?> - escape($tpl->dump($value)) ?> + dump($value) ?> diff --git a/src/Whoops/Resources/views/frame_list.html.php b/src/Whoops/Resources/views/frame_list.html.php index d4b0697..592926c 100644 --- a/src/Whoops/Resources/views/frame_list.html.php +++ b/src/Whoops/Resources/views/frame_list.html.php @@ -7,6 +7,7 @@ escape($frame->getClass() ?: '') ?> escape($frame->getFunction() ?: '') ?> + dumpArgs($frame); ?> @@ -14,4 +15,4 @@ -->getLine() ?> - + diff --git a/src/Whoops/Util/TemplateHelper.php b/src/Whoops/Util/TemplateHelper.php index 8531746..2c3b600 100644 --- a/src/Whoops/Util/TemplateHelper.php +++ b/src/Whoops/Util/TemplateHelper.php @@ -9,6 +9,7 @@ namespace Whoops\Util; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\CliDumper; use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Whoops\Exception\Frame; /** * Exposes useful tools for working with/in templates @@ -62,6 +63,34 @@ class TemplateHelper ); } + private function getDumper() + { + static $dumper = null; + + if (!$dumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) { + // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump. + $dumper = new HtmlDumper(); + + $styles = array( + 'default' => '', + 'num' => '', + 'const' => '', + 'str' => '', + 'note' => '', + 'ref' => '', + 'public' => '', + 'protected' => '', + 'private' => '', + 'meta' => '', + 'key' => '', + 'index' => '', + ); + $dumper->setStyles($styles); + } + + return $dumper; + } + /** * Format the given value into a human readable string. * @@ -70,36 +99,55 @@ class TemplateHelper */ public function dump($value) { - if (class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) { - static $dumper = null; - - // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump. - if (!$dumper) { - $dumper = new HtmlDumper(); - - $styles = array( - 'default' => '', - 'num' => '', - 'const' => '', - 'str' => '', - 'note' => '', - 'ref' => '', - 'public' => '', - 'protected' => '', - 'private' => '', - 'meta' => '', - 'key' => '', - 'index' => '', - ); - $dumper->setStyles($styles); - } + $dumper = $this->getDumper(); + if ($dumper) { $cloner = new VarCloner(); - return $dumper->dump($cloner->cloneVar($value)); + $output = ''; + $dumper->dump($cloner->cloneVar($value), function ($line, $depth) use (&$output) { + // A negative depth means "end of dump" + if ($depth >= 0) { + // Adds a two spaces indentation to the line + $output .= str_repeat(' ', $depth).$line."\n"; + } + }); + return $output; } + return print_r($value, true); } + /** + * Format the args of the given Frame as a human readable html string + * + * @param Frame $frame + * @return string the rendered html + */ + public function dumpArgs(Frame $frame) + { + // we support frame args only when the optional dumper is available + if (!$this->getDumper()) { + return ''; + } + + $html = ''; + $numFrames = count($frame->getArgs()); + + if ($numFrames > 0) { + $html .= '('; + foreach($frame->getArgs() as $j => $frameArg) { + $class = 'frame-arg'; + if ($j != $numFrames - 1 ) { + $class .= ' frame-arg-separated'; + } + $html .= ''. $this->dump($frameArg) .''; + } + $html .= ')'; + } + + return $html; + } + /** * Convert a string to a slug version of itself * From 186d299d477b32c083645e108f6d7fb025e3fec3 Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:17:52 +0530 Subject: [PATCH 02/10] Require symfony/var-dumper for development --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4a5be95..85d6fc2 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ }, "require-dev": { "phpunit/phpunit": "^4.8 || ^5.0", - "mockery/mockery": "0.9.*" + "mockery/mockery": "0.9.*", + "symfony/var-dumper": "~3.0" }, "suggest": { "symfony/var-dumper": "Pretty print complex values better with var-dumper available", From 3df80b1539befe5899f1cf824709305eff086fc4 Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:28:02 +0530 Subject: [PATCH 03/10] Use property instead of static variable --- src/Whoops/Util/TemplateHelper.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Whoops/Util/TemplateHelper.php b/src/Whoops/Util/TemplateHelper.php index 2c3b600..b750f46 100644 --- a/src/Whoops/Util/TemplateHelper.php +++ b/src/Whoops/Util/TemplateHelper.php @@ -22,6 +22,11 @@ class TemplateHelper */ private $variables = array(); + /** + * @var HtmlDumper + */ + private $htmlDumper; + /** * Escapes a string for output in an HTML document * @@ -65,11 +70,9 @@ class TemplateHelper private function getDumper() { - static $dumper = null; - - if (!$dumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) { + if (!$this->htmlDumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) { // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump. - $dumper = new HtmlDumper(); + $this->htmlDumper = new HtmlDumper(); $styles = array( 'default' => '', @@ -85,10 +88,10 @@ class TemplateHelper 'key' => '', 'index' => '', ); - $dumper->setStyles($styles); + $this->htmlDumper->setStyles($styles); } - return $dumper; + return $this->htmlDumper; } /** From 122c8c13d68131b268c5d91d55a3cdefae6c193d Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:36:33 +0530 Subject: [PATCH 04/10] Use a callable class instead of a closure as second argument to HtmlDumper::dump HtmlDumper::dump calls HtmlDumper::setOutput and this method resets the headerIsDumped property every time the $output argument changes. This results in including the global styles and scripts on each dump. We prevent this from happening by reusing the same HtmlDumperOutput object. --- src/Whoops/Util/HtmlDumperOutput.php | 32 ++++++++++++++++++++++++++++ src/Whoops/Util/TemplateHelper.php | 23 ++++++++++++-------- 2 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 src/Whoops/Util/HtmlDumperOutput.php diff --git a/src/Whoops/Util/HtmlDumperOutput.php b/src/Whoops/Util/HtmlDumperOutput.php new file mode 100644 index 0000000..c6786d6 --- /dev/null +++ b/src/Whoops/Util/HtmlDumperOutput.php @@ -0,0 +1,32 @@ + + */ + +namespace Whoops\Util; + +class HtmlDumperOutput +{ + private $output; + + public function __invoke($line, $depth) + { + // A negative depth means "end of dump" + if ($depth >= 0) { + // Adds a two spaces indentation to the line + $this->output .= str_repeat(' ', $depth) . $line . "\n"; + } + } + + public function getOutput() + { + return $this->output; + } + + public function clear() + { + $this->output = null; + } + +} diff --git a/src/Whoops/Util/TemplateHelper.php b/src/Whoops/Util/TemplateHelper.php index b750f46..2d0517c 100644 --- a/src/Whoops/Util/TemplateHelper.php +++ b/src/Whoops/Util/TemplateHelper.php @@ -27,6 +27,11 @@ class TemplateHelper */ private $htmlDumper; + /** + * @var HtmlDumperOutput + */ + private $htmlDumperOutput; + /** * Escapes a string for output in an HTML document * @@ -71,8 +76,9 @@ class TemplateHelper private function getDumper() { if (!$this->htmlDumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) { + $this->htmlDumperOutput = new HtmlDumperOutput(); // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump. - $this->htmlDumper = new HtmlDumper(); + $this->htmlDumper = new HtmlDumper($this->htmlDumperOutput); $styles = array( 'default' => '', @@ -106,14 +112,13 @@ class TemplateHelper if ($dumper) { $cloner = new VarCloner(); - $output = ''; - $dumper->dump($cloner->cloneVar($value), function ($line, $depth) use (&$output) { - // A negative depth means "end of dump" - if ($depth >= 0) { - // Adds a two spaces indentation to the line - $output .= str_repeat(' ', $depth).$line."\n"; - } - }); + + // re-use the same DumpOutput instance, so it won't re-render the global styles/scripts on each dump. + $dumper->dump($cloner->cloneVar($value), $this->htmlDumperOutput); + + $output = $this->htmlDumperOutput->getOutput(); + $this->htmlDumperOutput->clear(); + return $output; } From 0c87a150e11e2a8ab8c75d8cb7bced6b0ada5644 Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:37:38 +0530 Subject: [PATCH 05/10] Remove unused use statement --- src/Whoops/Util/TemplateHelper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Whoops/Util/TemplateHelper.php b/src/Whoops/Util/TemplateHelper.php index 2d0517c..20887c8 100644 --- a/src/Whoops/Util/TemplateHelper.php +++ b/src/Whoops/Util/TemplateHelper.php @@ -7,7 +7,6 @@ namespace Whoops\Util; use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Whoops\Exception\Frame; From 1ebda61309ffb23db6816aae8ffdbc1fd12422c1 Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:40:15 +0530 Subject: [PATCH 06/10] Dump the frame arguments below the source code --- src/Whoops/Resources/css/whoops.base.css | 11 +---------- src/Whoops/Resources/views/frame_code.html.php | 10 ++++++++++ src/Whoops/Resources/views/frame_list.html.php | 1 - src/Whoops/Util/TemplateHelper.php | 10 +++------- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/Whoops/Resources/css/whoops.base.css b/src/Whoops/Resources/css/whoops.base.css index b0a2471..0f22925 100644 --- a/src/Whoops/Resources/css/whoops.base.css +++ b/src/Whoops/Resources/css/whoops.base.css @@ -136,15 +136,6 @@ header { font-size: 14px; } - .frame-arg { - margin-left: 20px; - display: block; - } - - .frame-arg-separated .sf-dump::after { - content: ','; - } - .frame-index { font-size: 11px; color: #a29d9d; @@ -322,7 +313,7 @@ pre .xsl, code .xsl { color: #d0a0d0; } /* xslt tag */ pre .atn, code .atn { color: #ef7c61; font-weight: normal;} /* html/xml attribute name */ pre .atv, code .atv { color: #bcd42a; } /* html/xml attribute value */ pre .dec, code .dec { color: #606; } /* decimal */ -pre.prettyprint, code.prettyprint { +pre.prettyprint, code.prettyprint, .frame-args.prettyprint, .frame-args.prettyprint samp { font-family: "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace; background: #333; color: #e9e4e5; diff --git a/src/Whoops/Resources/views/frame_code.html.php b/src/Whoops/Resources/views/frame_code.html.php index b8fcbe2..9bd1973 100644 --- a/src/Whoops/Resources/views/frame_code.html.php +++ b/src/Whoops/Resources/views/frame_code.html.php @@ -47,6 +47,16 @@ + dumpArgs($frame); ?> + +
+ Arguments +
+
+ +
+ + getComments(); diff --git a/src/Whoops/Resources/views/frame_list.html.php b/src/Whoops/Resources/views/frame_list.html.php index 592926c..004ed3a 100644 --- a/src/Whoops/Resources/views/frame_list.html.php +++ b/src/Whoops/Resources/views/frame_list.html.php @@ -7,7 +7,6 @@ escape($frame->getClass() ?: '') ?> escape($frame->getFunction() ?: '') ?> - dumpArgs($frame); ?> diff --git a/src/Whoops/Util/TemplateHelper.php b/src/Whoops/Util/TemplateHelper.php index 20887c8..7d8e291 100644 --- a/src/Whoops/Util/TemplateHelper.php +++ b/src/Whoops/Util/TemplateHelper.php @@ -141,15 +141,11 @@ class TemplateHelper $numFrames = count($frame->getArgs()); if ($numFrames > 0) { - $html .= '('; + $html = '
    '; foreach($frame->getArgs() as $j => $frameArg) { - $class = 'frame-arg'; - if ($j != $numFrames - 1 ) { - $class .= ' frame-arg-separated'; - } - $html .= ''. $this->dump($frameArg) .''; + $html .= '
  1. '. $this->dump($frameArg) .'
  2. '; } - $html .= ')'; + $html .= '
'; } return $html; From f73af14a5c47a7c5b19214615ec2f978e42bfbae Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:42:18 +0530 Subject: [PATCH 07/10] Update syntax highlighting of the dumped vars Tries to be as close as possible to the source code syntax highlighting. --- src/Whoops/Util/TemplateHelper.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Whoops/Util/TemplateHelper.php b/src/Whoops/Util/TemplateHelper.php index 7d8e291..0b0d07f 100644 --- a/src/Whoops/Util/TemplateHelper.php +++ b/src/Whoops/Util/TemplateHelper.php @@ -80,18 +80,18 @@ class TemplateHelper $this->htmlDumper = new HtmlDumper($this->htmlDumperOutput); $styles = array( - 'default' => '', - 'num' => '', - 'const' => '', - 'str' => '', - 'note' => '', - 'ref' => '', - 'public' => '', - 'protected' => '', - 'private' => '', - 'meta' => '', - 'key' => '', - 'index' => '', + 'default' => 'color:#FFFFFF; line-height:normal; font:12px "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace !important; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: normal', + 'num' => 'color:#BCD42A', + 'const' => 'color: #4bb1b1;', + 'str' => 'color:#BCD42A', + 'note' => 'color:#ef7c61', + 'ref' => 'color:#A0A0A0', + 'public' => 'color:#FFFFFF', + 'protected' => 'color:#FFFFFF', + 'private' => 'color:#FFFFFF', + 'meta' => 'color:#FFFFFF', + 'key' => 'color:#BCD42A', + 'index' => 'color:#ef7c61', ); $this->htmlDumper->setStyles($styles); } From 4a3bb5258184e7fda37eb9191da8a1cbcf1fcd36 Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:43:13 +0530 Subject: [PATCH 08/10] Don't use syntax highlighting in the details section --- src/Whoops/Resources/css/whoops.base.css | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Whoops/Resources/css/whoops.base.css b/src/Whoops/Resources/css/whoops.base.css index 0f22925..7c11d52 100644 --- a/src/Whoops/Resources/css/whoops.base.css +++ b/src/Whoops/Resources/css/whoops.base.css @@ -94,6 +94,26 @@ header { border-bottom: 1px solid rgba(0, 0, 0, .1); } + .details pre.sf-dump { + white-space: pre; + word-wrap: inherit; + } + + .details pre.sf-dump, + .details pre.sf-dump .sf-dump-num, + .details pre.sf-dump .sf-dump-const, + .details pre.sf-dump .sf-dump-str, + .details pre.sf-dump .sf-dump-note, + .details pre.sf-dump .sf-dump-ref, + .details pre.sf-dump .sf-dump-public, + .details pre.sf-dump .sf-dump-protected, + .details pre.sf-dump .sf-dump-private, + .details pre.sf-dump .sf-dump-meta, + .details pre.sf-dump .sf-dump-key, + .details pre.sf-dump .sf-dump-index { + color: #463C54; + } + .left-panel { height: 100%; overflow: auto; From 965284ea67881041209863e8237caebffbeb02ec Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 11:43:49 +0530 Subject: [PATCH 09/10] Close the by default expanded objects of dumped vars --- src/Whoops/Resources/js/whoops.base.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Whoops/Resources/js/whoops.base.js b/src/Whoops/Resources/js/whoops.base.js index a67e809..ed3db16 100644 --- a/src/Whoops/Resources/js/whoops.base.js +++ b/src/Whoops/Resources/js/whoops.base.js @@ -119,4 +119,10 @@ Zepto(function($) { e.preventDefault(); $.get(this.href); }); + + // Symfony VarDumper: Close the by default expanded objects + $('.sf-dump-expanded') + .removeClass('sf-dump-expanded') + .addClass('sf-dump-compact'); + $('.sf-dump-toggle span').html('▶'); }); From d801002839d01c3e3e8c9e567e80c378948d833b Mon Sep 17 00:00:00 2001 From: Jonas De Taeye Date: Thu, 18 Feb 2016 22:28:37 +0530 Subject: [PATCH 10/10] Add description to HtmlDumperOutput --- src/Whoops/Util/HtmlDumperOutput.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Whoops/Util/HtmlDumperOutput.php b/src/Whoops/Util/HtmlDumperOutput.php index c6786d6..7486323 100644 --- a/src/Whoops/Util/HtmlDumperOutput.php +++ b/src/Whoops/Util/HtmlDumperOutput.php @@ -6,6 +6,11 @@ namespace Whoops\Util; +/** + * Used as output callable for Symfony\Component\VarDumper\Dumper\HtmlDumper::dump() + * + * @see TemplateHelper::dump() + */ class HtmlDumperOutput { private $output;