Skip to content

Commit f51ade1

Browse files
committed
init
0 parents  commit f51ade1

3 files changed

Lines changed: 365 additions & 0 deletions

File tree

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
Copyright (c) 2010 widowmaker
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
20+
OR OTHER DEALINGS IN THE SOFTWARE.

composer.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "paulloft/dumphper",
3+
"description": "Makes handling and debugging PHP errors suck less.",
4+
"keywords": ["error", "exception", "error handler", "exception handler", "fatal", "debug", "debugger"],
5+
"license": "MIT",
6+
"require": {
7+
"php": ">=5.3.0",
8+
},
9+
"autoload": {
10+
"psr-4": {
11+
"Dumphper": "src"
12+
}
13+
}
14+
}

src/Dumphper.php

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
<?php
2+
namespace Dumphper;
3+
/**
4+
* Impored var_dump for PHP 5.2.3++
5+
* @author Dmitry "widowmaker" Khavilo
6+
* @email wm .dot. morgun .at. gmail .dot. com
7+
**/
8+
9+
// Fixed by S
10+
11+
define('DPHP_USE_ACCESSIBLE', true);
12+
13+
class Dumphper
14+
{
15+
/** config **/
16+
17+
static $encoding = 'UTF-8'; /** Text encoding, needed to escape stings **/
18+
static $escape_keys = false; /** Should array keys be escaped (slow) **/
19+
static $max_showw_depth = 8; /** Defines how many nested levels will be expanded by default **/
20+
21+
/** don't touch **/
22+
static $objects = array();
23+
static $calls = 0;
24+
static $depth = 0;
25+
static $objectStorage;
26+
27+
static function dump(&$source)
28+
{
29+
if (class_exists('SplObjectStorage')) {
30+
self::$objectStorage = new SplObjectStorage();
31+
}
32+
self::$depth = 0;
33+
self::drawStyles();
34+
//$s = microtime(true);
35+
//self::$objects = array();
36+
self::$calls++;
37+
echo '<div class="dumphper">';
38+
self::_dump($source);
39+
echo '</div>';
40+
//echo round(microtime(true) - $s,6)*1000 . 's';
41+
}
42+
43+
static function _dump(&$source, &$parents = array())
44+
{
45+
self::$depth++;
46+
switch(gettype($source))
47+
{
48+
case 'array':
49+
self::drawArray($source, $parents);
50+
break;
51+
case 'object':
52+
self::drawObject($source, $parents);
53+
break;
54+
case 'NULL':
55+
self::drawNULL();
56+
break;
57+
case 'boolean':
58+
self::drawBoolean($source);
59+
break;
60+
case 'resource':
61+
self::drawResource($source);
62+
break;
63+
default:
64+
self::drawScalar($source);
65+
break;
66+
}
67+
self::$depth--;
68+
}
69+
70+
static function escape(&$source)
71+
{
72+
return ( is_string($source) ? ( $source ? htmlentities($source, ENT_QUOTES, self::$encoding) : '&nbsp;') : $source );
73+
}
74+
75+
static function drawScalar(&$source, &$escape = true)
76+
{
77+
if ($source === '0') $escape = False;
78+
$type = gettype($source);
79+
// $type = $type == 'string' ? $type.'('.mb_strlen($value).')' : $type;
80+
$value = $escape ? self::escape($source) : $source;
81+
$value = $type == 'string' ? '<span class="strlen">('.mb_strlen($source).')</span>'.$value : $value;
82+
83+
self::drawValue($value, $type);
84+
}
85+
86+
static function drawNULL()
87+
{
88+
self::drawValue('NULL', 'null');
89+
}
90+
91+
static function drawResource(&$source)
92+
{
93+
self::drawValue(get_resource_type($source) . ' ' . strtolower((string)$source) , 'resource');
94+
}
95+
96+
static function drawBoolean(&$source)
97+
{
98+
self::drawValue($source ? 'true' : 'false', 'boolean');
99+
}
100+
101+
static function drawArray(&$source, &$parents)
102+
{
103+
if (self::isRecursiveArray($source, $parents))
104+
{
105+
self::drawValue('RECURSION', 'recursion');
106+
}
107+
else
108+
{
109+
$c = count($source);
110+
echo '<div class="dumphper-container' . (self::$depth <= self::$max_showw_depth ? '' : ' dumphper-closed') . '">';
111+
self::drawHeader( $c > 0 ? '<a class="dumphper-toggler" href="javascript:;" onclick="dumphper_toggle(this);">Array (' . $c . ')</a>' : 'empty Array ', 'array');
112+
if ( $c > 0 )
113+
{
114+
echo '<table class="dumphper-table" cellspacing="0" cellpadding="0">';
115+
foreach ($source as $key => &$value)
116+
{
117+
echo '<tr><td class="dumphper-key-array">';
118+
self::drawScalar($key, self::$escape_keys);
119+
echo '</td><td>';
120+
self::_dump($value, $parents);
121+
echo '</td></tr>';
122+
}
123+
echo '</table>';
124+
}
125+
echo '</div>';
126+
}
127+
}
128+
129+
static function getObjectId(&$source)
130+
{
131+
$class = get_class($source);
132+
if ( !isset(self::$objects[$class]) )
133+
self::$objects[$class] = array();
134+
foreach (self::$objects[$class] as $id => $obj)
135+
if ( $source === $obj )
136+
return $id;
137+
self::$objects[$class][] = &$source;
138+
return count(self::$objects[$class])-1;
139+
}
140+
141+
static function drawObject(&$source, &$parents)
142+
{
143+
$className = get_class($source);
144+
$object_index = self::getObjectId($source);
145+
$object_id = 'dhph_' . $className . '_' . self::$calls . '_' . $object_index;
146+
147+
if (self::isRecursiveObject($source, $parents))
148+
{
149+
self::drawValue('<a href="#' . $object_id . '" onclick="dumphper_show(this);">' . $className . ' #' . $object_index . '</a>' , 'recursion');
150+
}
151+
else
152+
{
153+
$sClass = new ReflectionObject($source);
154+
$statics = null;
155+
$class = $sClass->getParentClass();
156+
$classArray = '';
157+
while ( is_object($class) )
158+
{
159+
$classArray = ' &gt; ' . $class->getName() . $classArray;
160+
$class = $class->getParentClass();
161+
}
162+
163+
echo '<div class="dumphper-container' . (self::$depth <= self::$max_showw_depth ? '' : ' dumphper-closed') . '">';
164+
self::drawHeader( '<a id="' . $object_id . '" name="' . $object_id . '" class="dumphper-toggler" href="javascript:;" onclick="dumphper_toggle(this);">' . $className . ' #' . $object_index .
165+
(count($classArray) ? ' <span class="dumphper-class-def"> ' . $classArray . '</span>' : '' ).
166+
'</a>', 'object');
167+
echo '<table class="dumphper-table" cellspacing="0" cellpadding="0">';
168+
169+
if(!DPHP_USE_ACCESSIBLE)
170+
$temp = (array)$source;
171+
172+
$class = $sClass;
173+
while ( is_object($class) )
174+
{
175+
$properties = $class->getProperties();
176+
if ($class->name != $className && count($properties))
177+
{
178+
echo '<tr><td colspan = "2">';
179+
self::drawValue('<code>inherited from </code>' . $class->name . ':', 'inherited');
180+
echo '</td></tr>';
181+
}
182+
foreach ($properties as &$value)
183+
{
184+
$declaredClass = $value->getDeclaringClass()->name;
185+
if ($class->name == $declaredClass)
186+
{
187+
echo '<tr><td class="dumphper-key-object">';
188+
self::drawValue($value->name/* . ' <span class="dumphper-class-def">' . $declaredClass . '</span>'*/, join('-',Reflection::getModifierNames($value->getModifiers())));
189+
echo '</td><td>';
190+
if ($value->isPublic()) {
191+
$tmp = $value->getValue($source);
192+
self::_dump($tmp, $parents);
193+
}
194+
/** in case of PHP 5.3+ **/
195+
elseif (DPHP_USE_ACCESSIBLE)
196+
{
197+
$value->setAccessible(true);
198+
$tmp = $value->getValue($source);
199+
self::_dump($tmp, $parents);
200+
}
201+
/** in case of PHP 5.2.x+ **/
202+
elseif ($value->isStatic())
203+
{
204+
if (!$statics) $statics = $class->getStaticProperties();
205+
self::_dump($statics[$value->name], $parents);
206+
}
207+
else
208+
{
209+
$scope = $value->isPrivate() ? $value->class : '*';
210+
self::_dump($temp["\0{$scope}\0{$value->name}"], $parents);
211+
}
212+
echo '</td></tr>';
213+
}
214+
}
215+
$class = $class->getParentClass();
216+
}
217+
echo '</table>';
218+
echo '</div>';
219+
}
220+
}
221+
222+
static function isRecursiveArray(&$source, &$parents)
223+
{
224+
if ( count($parents) > 0 )
225+
{
226+
$uKey = uniqid('array', true);
227+
$source[$uKey] = true;
228+
foreach ( $parents as &$parrent )
229+
{
230+
if ( is_array($parrent) && isset($parrent[$uKey]) )
231+
{
232+
unset($source[$uKey]);
233+
return true;
234+
}
235+
}
236+
unset($source[$uKey]);
237+
}
238+
$parents[] = &$source;
239+
return false;
240+
}
241+
242+
static function isRecursiveObject(&$source, &$parents)
243+
{
244+
if (self::$objectStorage) {
245+
if (self::$objectStorage->contains($source)) {
246+
return true;
247+
}
248+
self::$objectStorage->attach($source);
249+
} else {
250+
if ( in_array($source, $parents, true) ) {
251+
return true;
252+
}
253+
$parents[] = &$source;
254+
}
255+
return false;
256+
}
257+
258+
static function drawValue($value, $type)
259+
{
260+
echo '<span class="dumphper-value dumphper-' . $type . '" title="' . $type . '">' . $value . '</span>';
261+
}
262+
263+
static function drawHeader($value, $type)
264+
{
265+
echo '<div class="dumphper-head dumphper-head-' . $type . '" title="' . $type . '">' . $value .'</div>';
266+
}
267+
268+
static function drawStyles()
269+
{
270+
static $displayed = false;
271+
if ($displayed) return; //Exit if already shown
272+
$displayed = true;
273+
?><style type="text/css">
274+
.dumphper { margin: 0 0 3px !important; /*max-width:500px !important;*/}
275+
.dumphper-container { display: inline-block !important; position: relative !important; }
276+
.dumphper-value { background-color: #e7e7e7 !important; border: 1px solid #888 !important; }
277+
.dumphper-table { border-left: 1px solid #888 !important; width: 100%; }
278+
.dumphper-table td { border-right: 1px solid #888 !important; border-bottom: 1px solid #888 !important; vertical-align: top !important;}
279+
.dumphper-table .dumphper-value { border-width: 0 0 0 0 !important;display: block;}
280+
.dumphper, .dumphper-value, .dumphper-key, .dumphper-head { font: normal 12px Arial !important; line-height: 15px !important;}
281+
.dumphper-value { padding: 0 3px 0 12px !important; background-repeat: no-repeat !important; cursor: default !important;max-height: 45px; overflow: auto;}
282+
.dumphper-key { padding: 0 3px !important; }
283+
.dumphper-head { color: #fff !important; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAJCAYAAADzRkbkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACRJREFUeNpi+P//fw8TAwPDfxDxFUR8gROf4axvDEB10gABBgAvWg1pnyJeXQAAAABJRU5ErkJggg==) !important; background-repeat: repeat-x !important; padding: 1px 3px 2px !important; border: 1px solid #888 !important; font-weight: bold !important; }
284+
.dumphper-head-array { background-color: #260 !important;}
285+
.dumphper-key-array, .dumphper-key-array .dumphper-value { background-color: #dcffd0 !important;}
286+
.dumphper-key-array .dumphper-string { color: #030 !important; }
287+
.dumphper-key-array .dumphper-string, .dumphper-key-array .dumphper-integer { background-image: none !important; padding-left: 3px !important;}
288+
.dumphper-key-object { color: #004 !important;}
289+
.dumphper-head-object { background-color: #006 !important;}
290+
.dumphper-key-object, .dumphper-key-object .dumphper-value { background-color: #c8defe !important; }
291+
.dumphper-class-def { color: #666 !important; font: bold oblique 11px Arial !important;}
292+
.dumphper-head-object .dumphper-class-def { color: #bbb !important;}
293+
.dumphper-string { color: #a40 !important; background-image: url(data:image/gif;base64,R0lGODlhCgASAIAAAP/Qmv///yH5BAAAAAAALAAAAAAKABIAAAISjI+py+0MYkRzSQBlpvf5D34FADs=) !important; }
294+
.dumphper-string .strlen { display: inline-block; background: none; color: #000; font-size: 8px; margin-right: 3px; vertical-align: bottom;}
295+
.dumphper-integer { color: #00f !important; background-image: url(data:image/gif;base64,R0lGODlhCgASAIAAAKTC/////yH5BAAAAAAALAAAAAAKABIAAAIVjI+pqwDsGHRvRVtbThdRKoXiSC4FADs=) !important; }
296+
.dumphper-double { color: #f00 !important; background-image: url(data:image/gif;base64,R0lGODlhCgASAIAAAP+/v////yH5BAAAAAAALAAAAAAKABIAAAIWjI+pu+CQHJPxUXTrhI1j6zHiSJZiAQA7) !important; }
297+
.dumphper-resource { color: #660 !important; background-image: url(data:image/gif;base64,R0lGODlhCgASAIAAAP///8zMfyH5BAAAAAAALAAAAAAKABIAAAIVhI+py+0bYgAxSWon1Kpm6T3iSDYFADs=) !important; }
298+
.dumphper-null { color: #000 !important; background-image: url(data:image/gif;base64,R0lGODlhIgASAIAAAL+/v////yH5BAAAAAAALAAAAAAiABIAAAI+jI+py+0Po5wBWHAupswmzy1gtiEaeFWj+pXmhsLuyiqxcZOtKOO9/uL5hjUi8CVLpk4YZugJjUqn1KqVUQAAOw==) !important; padding-left: 37px !important; }
299+
.dumphper-boolean { color: #000 !important; background-image: url(data:image/gif;base64,R0lGODlhIgASAIAAAL+/v////yH5BAAAAAAALAAAAAAiABIAAAI+jI+py+0PYwRULlpVthpcz3VfsJEYgoFGeZzZC8Ktisb2epvzqPdyD6x5fkQVyzSkpYS2ZegJjUqn1KqVUwAAOw==) !important; padding-left: 37px !important; }
300+
.dumphper-inherited { color: #009 !important; background-color: #c8defe !important; /*background-image: url(data:image/gif;base64,R0lGODlhSgASAIABAH9/5f///yH5BAEAAAEALAAAAABKABIAAAJ2jI+py+0Po5y02ospAHDzbGyZt4jdB5ohGqmXCyLwA3uo7eIyGdj951vxfjnO7LdbHUxM4E3EKiaRyOFUSaU2g9lrF+fEJqTZpti7jKoVZva6HC6nS2/jTWklknj7rdDJBZb2JJUXc4iYqLjI2Oj4CBkpOblYAAA7) !important;*/ padding-left: /*7*/4px !important; font-weight: bold !important; }
301+
.dumphper-inherited code { font: 12px Arial; color: #66c !important; }
302+
.dumphper-recursion { color: #609 !important; background-image: url(data:image/gif;base64,R0lGODlhEAASAIAAAP/Uf////yH5BAAAAAAALAAAAAAQABIAAAIejI+py+0PIwMUmGoRvZXrHGzeIWIj2YWpxLbuC0sFADs=) !important; padding-left: 19px !important; font-weight: bold !important; }
303+
.dumphper-recursion a { color: #609 !important; text-decoration: underline !important; }
304+
.dumphper-private { background-image: url(data:image/gif;base64,R0lGODlhCwASAJEAAP///zMzM/8zMwAAACH5BAAAAAAALAAAAAALABIAAAIdhI+py30RWhCRzfrgpGhTwRnahnVhclmlw7auUwAAOw==) !important;}
305+
.dumphper-protected { background-image: url(data:image/gif;base64,R0lGODlhCwASAJEAAP/eADMzM////wAAACH5BAAAAAAALAAAAAALABIAAAIdlI+py30RWgCRzfrgpGhTwBnahnVhclmlw7auUwAAOw==) !important;}
306+
.dumphper-public { background-image: url(data:image/gif;base64,R0lGODlhCwASAJEAAADdADMzM////wAAACH5BAAAAAAALAAAAAALABIAAAIdlI+py30RWgCRzfrgpGhTwBnahnVhclmlw7auUwAAOw==) !important;}
307+
.dumphper-private-static { background-image: url(data:image/gif;base64,R0lGODlhCwASAJEAAP///zMzM/8zMwAAACH5BAAAAAAALAAAAAALABIAAAIdhI+pyw0BY0BBiHqpxfPI6CQfpF1byVFjyLbuUgAAOw==) !important;}
308+
.dumphper-protected-static { background-image: url(data:image/gif;base64,R0lGODlhCwASAJEAAP///zMzM//eAAAAACH5BAAAAAAALAAAAAALABIAAAIdhI+pyw0BY0BBiHqpxfPI6CQfpF1byVFjyLbuUgAAOw==) !important;}
309+
.dumphper-public-static { background-image: url(data:image/gif;base64,R0lGODlhCwASAJEAAP///zMzMwDdAAAAACH5BAAAAAAALAAAAAALABIAAAIdhI+pyw0BY0BBiHqpxfPI6CQfpF1byVFjyLbuUgAAOw==) !important;}
310+
.dumphper-toggler { color: #fff !important; display: block; background: url(data:image/gif;base64,R0lGODlhCgAKAJEAAOfn5zMzM////wAAACH5BAEAAAIALAAAAAAKAAoAAAISlI+pe+HvRAC0UmdtkPCxDyIFADs=) 1px 3px no-repeat !important; padding-left: 14px !important; text-decoration: none !important; cursor: pointer !important;}
311+
.dumphper-closed .dumphper-toggler { background-image: url(data:image/gif;base64,R0lGODlhCgAKAJEAAOfn5zMzM////wAAACH5BAEAAAIALAAAAAAKAAoAAAIZlBVxGwC6kIMmtZek2/PyiSQdpZEVGIVLAQA7) !important; }
312+
.dumphper-closed .dumphper-table, .dumphper-closed .dumphper-class-def { display: none !important; }
313+
</style>
314+
<script type="text/javascript">
315+
function dumphper_toggle(obj)
316+
{
317+
obj.parentNode.parentNode.className = (obj.parentNode.parentNode.className == 'dumphper-container' ? 'dumphper-container dumphper-closed' : 'dumphper-container');
318+
}
319+
function dumphper_show(source_obj)
320+
{
321+
obj = document.getElementById(source_obj.href.match(/[^#]+$/));
322+
while(obj = obj.parentNode)
323+
if (obj.className == 'dumphper-container dumphper-closed')
324+
obj.className = 'dumphper-container';
325+
}
326+
</script><?php
327+
}
328+
}
329+
330+
/** Comment if you don't need this **/
331+
//function dump(&$var) { Dumphper::dump($var); }

0 commit comments

Comments
 (0)