Skip to content

Commit

Permalink
Refactoring, adjust output style, dump closures as object for JSON fo…
Browse files Browse the repository at this point in the history
…rmat
  • Loading branch information
xepozz committed Nov 28, 2020
1 parent 47fe5a5 commit 9241213
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 56 deletions.
86 changes: 44 additions & 42 deletions src/VarDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
final class VarDumper
{
private $variable;
private static array $objects = [];
private array $objects = [];

private ?ClosureExporter $closureExporter = null;

Expand Down Expand Up @@ -87,7 +87,7 @@ public function asJsonObjectsMap(int $depth = 50, bool $prettyPrint = false): st
{
$this->buildObjectsCache($this->variable, $depth);

return $this->asJsonInternal(self::$objects, $prettyPrint, $depth, 1);
return $this->asJsonInternal($this->objects, $prettyPrint, $depth, 1);
}

/**
Expand Down Expand Up @@ -116,10 +116,10 @@ private function buildObjectsCache($variable, int $depth, int $level = 0): void
return;
}
if (is_object($variable)) {
if (in_array($variable, self::$objects, true)) {
if (in_array($variable, $this->objects, true)) {
return;
}
self::$objects[] = $variable;
$this->objects[] = $variable;
$variable = $this->getObjectProperties($variable);
}
if (is_array($variable)) {
Expand All @@ -140,44 +140,46 @@ private function dumpNestedInternal($var, int $depth, int $level, int $objectCol
}

$output = [];
foreach ($var as $key => $value) {
$keyDisplay = str_replace("\0", '::', trim((string)$key));
foreach ($var as $name => $value) {
$keyDisplay = str_replace("\0", '::', trim((string)$name));
$output[$keyDisplay] = $this->dumpNestedInternal($value, $depth, $level + 1, $objectCollapseLevel);
}

break;
case 'object':
$className = get_class($var);
/**
* @psalm-var array<string, array<string, array|string>> $output
*/
if (($objectCollapseLevel < $level) && (in_array($var, self::$objects, true))) {
if ($var instanceof \Closure) {
$output = $this->exportClosure($var);
} else {
$output = 'object@' . $this->getObjectDescription($var);
}
} elseif ($depth <= $level) {
$output = $className . ' (...)';
} else {
$output = [];
$mainKey = $this->getObjectDescription($var);
$dumpValues = $this->getObjectProperties($var);
if (empty($dumpValues)) {
$output[$mainKey] = '{stateless object}';
}
foreach ($dumpValues as $key => $value) {
$keyDisplay = $this->normalizeProperty((string)$key);
/**
* @psalm-suppress InvalidArrayOffset
*/
$output[$mainKey][$keyDisplay] = $this->dumpNestedInternal(
$value,
$depth,
$level + 1,
$objectCollapseLevel
);
}
$objectDescription = $this->getObjectDescription($var);
if ($depth <= $level) {
$output = $objectDescription . ' (...)';
break;
}

if ($var instanceof \Closure) {
$output = [$objectDescription => $this->exportClosure($var)];
break;
}

if ($objectCollapseLevel < $level && in_array($var, $this->objects, true)) {
$output = 'object@' . $objectDescription;
break;
}

$output = [];
$properties = $this->getObjectProperties($var);
if (empty($properties)) {
$output[$objectDescription] = '{stateless object}';
break;
}
foreach ($properties as $name => $value) {
$keyDisplay = $this->normalizeProperty((string) $name);
/**
* @psalm-suppress InvalidArrayOffset
*/
$output[$objectDescription][$keyDisplay] = $this->dumpNestedInternal(
$value,
$depth,
$level + 1,
$objectCollapseLevel
);
}

break;
Expand All @@ -194,14 +196,14 @@ private function normalizeProperty(string $property): string
$property = str_replace("\0", '::', trim($property));

if (strpos($property, '*::') === 0) {
return 'protected::' . substr($property, 3);
return 'protected $' . substr($property, 3);
}

if (($pos = strpos($property, '::')) !== false) {
return 'private::' . substr($property, $pos + 2);
return 'private $' . substr($property, $pos + 2);
}

return 'public::' . $property;
return 'public $' . $property;
}

/**
Expand Down Expand Up @@ -259,15 +261,15 @@ private function dumpInternal($var, int $depth, int $level): string
if ($var instanceof \Closure) {
return $this->exportClosure($var);
}
if (in_array($var, self::$objects, true)) {
if (in_array($var, $this->objects, true)) {
return $this->getObjectDescription($var) . '(...)';
}

if ($depth <= $level) {
return get_class($var) . '(...)';
}

self::$objects[] = $var;
$this->objects[] = $var;
$spaces = str_repeat(' ', $level * 4);
$output = $this->getObjectDescription($var) . "\n" . $spaces . '(';
$objectProperties = $this->getObjectProperties($var);
Expand Down
36 changes: 22 additions & 14 deletions tests/VarDumperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ static function () {
public function testAsJsonObjectsMap($var, $expectedResult): void
{
$exportResult = VarDumper::create($var)->asJsonObjectsMap();
$this->assertStringContainsString($expectedResult, $exportResult);
$this->assertEquals($expectedResult, $exportResult);
}

public function asJsonObjectMapDataProvider(): array
Expand All @@ -363,13 +363,13 @@ public function asJsonObjectMapDataProvider(): array
[
$user,
<<<S
"stdClass#{$objectId}":{"public::id":1}
[{"stdClass#{$objectId}":{"public \$id":1}}]
S,
],
[
$decoratedUser,
<<<S
"stdClass#{$decoratedObjectId}":{"public::id":1,"public::name":"Name","public::originalUser":"object@stdClass#{$objectId}"}
[{"stdClass#{$decoratedObjectId}":{"public \$id":1,"public \$name":"Name","public \$originalUser":"object@stdClass#{$objectId}"}},{"stdClass#{$objectId}":{"public \$id":1}}]
S,
],
];
Expand Down Expand Up @@ -405,6 +405,7 @@ public function jsonDataProvider(): array
$objectWithClosureInProperty->a = fn () => 1;
// @formatter:on
$objectWithClosureInPropertyId = spl_object_id($objectWithClosureInProperty);
$objectWithClosureInPropertyClosureId = spl_object_id($objectWithClosureInProperty->a);

$emptyObject = new stdClass();
$emptyObjectId = spl_object_id($emptyObject);
Expand Down Expand Up @@ -453,6 +454,11 @@ public function jsonDataProvider(): array
// @formatter:on
$closureWithAliasedNamespaceObjectId = spl_object_id($closureWithAliasedNamespaceObject);

// @formatter:off
$closureInArrayObject = fn () => new \DateTimeZone('');
// @formatter:on
$closureInArrayObjectId = spl_object_id($closureInArrayObject);

return [
'empty object' => [
$emptyObject,
Expand All @@ -463,25 +469,25 @@ public function jsonDataProvider(): array
'short function' => [
$shortFunctionObject,
<<<S
{"Closure#{$shortFunctionObjectId}":{"public::0":"fn () => 1"}}
{"Closure#{$shortFunctionObjectId}":"fn () => 1"}
S,
],
'short static function' => [
$staticShortFunctionObject,
<<<S
{"Closure#{$staticShortFunctionObjectId}":{"public::0":"static fn () => 1"}}
{"Closure#{$staticShortFunctionObjectId}":"static fn () => 1"}
S,
],
'function' => [
$functionObject,
<<<S
{"Closure#{$functionObjectId}":{"public::0":"function () {\\n return 1;\\n }"}}
{"Closure#{$functionObjectId}":"function () {\\n return 1;\\n }"}
S,
],
'static function' => [
$staticFunctionObject,
<<<S
{"Closure#{$staticFunctionObjectId}":{"public::0":"static function () {\\n return 1;\\n }"}}
{"Closure#{$staticFunctionObjectId}":"static function () {\\n return 1;\\n }"}
S,
],
'string' => [
Expand Down Expand Up @@ -534,32 +540,34 @@ public function jsonDataProvider(): array
],
'closure in array' => [
// @formatter:off
[fn () => new \DateTimeZone('')],
[$closureInArrayObject],
// @formatter:on
'["fn () => new \\\DateTimeZone(\'\')"]',
<<<S
[{"Closure#{$closureInArrayObjectId}":"fn () => new \\\DateTimeZone('')"}]
S,
],
'original class name' => [
$closureWithUsualClassNameObject,
<<<S
{"Closure#{$closureWithUsualClassNameObjectId}":{"public::0":"fn (\\\Yiisoft\\\VarDumper\\\VarDumper \$date) => new \\\DateTimeZone('')"}}
{"Closure#{$closureWithUsualClassNameObjectId}":"fn (\\\Yiisoft\\\VarDumper\\\VarDumper \$date) => new \\\DateTimeZone('')"}
S,
],
'class alias' => [
$closureWithAliasedClassNameObject,
<<<S
{"Closure#{$closureWithAliasedClassNameObjectId}":{"public::0":"fn (\\\Yiisoft\\\VarDumper\\\VarDumper \$date) => new \\\DateTimeZone('')"}}
{"Closure#{$closureWithAliasedClassNameObjectId}":"fn (\\\Yiisoft\\\VarDumper\\\VarDumper \$date) => new \\\DateTimeZone('')"}
S,
],
'namespace alias' => [
$closureWithAliasedNamespaceObject,
<<<S
{"Closure#{$closureWithAliasedNamespaceObjectId}":{"public::0":"fn (\\\Yiisoft\\\VarDumper\\\VarDumper \$date) => new \\\DateTimeZone('')"}}
{"Closure#{$closureWithAliasedNamespaceObjectId}":"fn (\\\Yiisoft\\\VarDumper\\\VarDumper \$date) => new \\\DateTimeZone('')"}
S,
],
'closure with null-collision operator' => [
$closureWithNullCollisionOperatorObject,
<<<S
{"Closure#{$closureWithNullCollisionOperatorObjectId}":{"public::0":"fn () => \$_ENV['var'] ?? null"}}
{"Closure#{$closureWithNullCollisionOperatorObjectId}":"fn () => \$_ENV['var'] ?? null"}
S,
],
'utf8 supported' => [
Expand All @@ -569,7 +577,7 @@ public function jsonDataProvider(): array
'closure in property supported' => [
$objectWithClosureInProperty,
<<<S
{"stdClass#{$objectWithClosureInPropertyId}":{"public::a":"fn () => 1"}}
{"stdClass#{$objectWithClosureInPropertyId}":{"public \$a":{"Closure#{$objectWithClosureInPropertyClosureId}":"fn () => 1"}}}
S,
],
'binary string' => [
Expand Down

0 comments on commit 9241213

Please sign in to comment.