Skip to content

Commit

Permalink
Merge pull request #75 from yiisoft/enhance
Browse files Browse the repository at this point in the history
Enhance
  • Loading branch information
xepozz committed Oct 28, 2022
2 parents 1231422 + 33c8184 commit d2cae7b
Show file tree
Hide file tree
Showing 3 changed files with 277 additions and 9 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -2,9 +2,9 @@

## 1.3.1 under development

- Enh #75: Add method `asPrimitives` that exports a variable like destructed json (@xepozz)
- Enh #74: Add support for integer property names (@xepozz)


## 1.3.0 September 22, 2022

- New #64, #68: Add `VarDumper::asJson()` method that provide exporting value as JSON string (@dood-, @xepozz)
Expand Down
27 changes: 19 additions & 8 deletions src/VarDumper.php
Expand Up @@ -148,7 +148,7 @@ public function asString(int $depth = 10, bool $highlight = false): string
public function asJson(bool $format = true, int $depth = 10): string
{
/** @var mixed $output */
$output = $this->exportJson($this->variable, $format, $depth, 0);
$output = $this->asPrimitives($depth);

if ($format) {
return json_encode($output, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT);
Expand All @@ -157,6 +157,20 @@ public function asJson(bool $format = true, int $depth = 10): string
return json_encode($output, JSON_THROW_ON_ERROR);
}

/**
* Dumps the variable as PHP primitives in JSON decoded style.
*
* @param int $depth Maximum depth that the dumper should go into the variable. Defaults to 10.
*
* @throws ReflectionException
*
* @return mixed
*/
public function asPrimitives(int $depth = 10): mixed
{
return $this->exportPrimitives($this->variable, $depth, 0);
}

/**
* Exports a variable as a string containing PHP code.
*
Expand Down Expand Up @@ -326,7 +340,6 @@ private function exportInternal($variable, bool $format, int $level): string

/**
* @param mixed $var
* @param bool $format
* @param int $depth
* @param int $level
*
Expand All @@ -335,7 +348,7 @@ private function exportInternal($variable, bool $format, int $level): string
* @return mixed
* @psalm-param mixed $var
*/
private function exportJson(mixed $var, bool $format, int $depth, int $level): mixed
private function exportPrimitives(mixed $var, int $depth, int $level): mixed
{
switch (gettype($var)) {
case 'resource':
Expand All @@ -349,9 +362,7 @@ private function exportJson(mixed $var, bool $format, int $depth, int $level): m
}

/** @psalm-suppress MissingClosureReturnType */
return array_map(function ($value) use ($format, $level, $depth) {
return $this->exportJson($value, $format, $depth, $level + 1);
}, $var);
return array_map(fn ($value) => $this->exportPrimitives($value, $depth, $level + 1), $var);
case 'object':
if ($var instanceof Closure) {
return $this->exportClosure($var);
Expand Down Expand Up @@ -380,9 +391,9 @@ private function exportJson(mixed $var, bool $format, int $depth, int $level): m
foreach ($objectProperties as $name => $value) {
$propertyName = $this->getPropertyName($name);
/** @psalm-suppress MixedAssignment */
$output[$propertyName] = $this->exportJson($value, $format, $depth, $level + 1);
$output[$propertyName] = $this->exportPrimitives($value, $depth, $level + 1);
}
return $output ;
return $output;
default:
return $var;
}
Expand Down
257 changes: 257 additions & 0 deletions tests/VarDumperTest.php
Expand Up @@ -1057,6 +1057,263 @@ static function () {
];
}

/**
* @dataProvider asPrimitivesDataProvider
*
* @param mixed $variable
* @param mixed $result
*
* @psalm-suppress MixedAssignment
*/
public function testAsPrimitives($variable, $result): void
{
$output = VarDumper::create($variable)->asPrimitives(depth: 3);
$this->assertEquals($result, $output);
}

public function asPrimitivesDataProvider(): array
{
$dummyDebugInfo = new DummyDebugInfo();
$dummyDebugInfo->volume = 10;
$dummyDebugInfo->unitPrice = 15;
$dummyDebugInfoObjectId = spl_object_id($dummyDebugInfo);

$incompleteObject = unserialize('O:16:"nonExistingClass":0:{}');
$incompleteObjectId = spl_object_id($incompleteObject);

$integerPropertyObject = unserialize('O:8:"stdClass":1:{i:5;i:5;}');
$integerPropertyObjectId = spl_object_id($integerPropertyObject);

$emptyObject = new stdClass();
$emptyObjectId = spl_object_id($emptyObject);

$nestedObject = new stdClass();
$nestedObject->nested = $nestedObject;
$nestedObjectId = spl_object_id($nestedObject);

$objectWithClosureInProperty = new stdClass();
// @formatter:off
$objectWithClosureInProperty->a = fn () => 1;
// @formatter:on
$objectWithClosureInPropertyId = spl_object_id($objectWithClosureInProperty);

$objectWithPrivateProperties = new PrivateProperties();
$objectWithPrivatePropertiesId = spl_object_id($objectWithPrivateProperties);
$objectWithPrivatePropertiesClass = PrivateProperties::class;

return [
'custom debug info' => [
$dummyDebugInfo,
[
'$__id__$' => $dummyDebugInfoObjectId,
'$__class__$' => DummyDebugInfo::class,
'volume' => 10,
'totalPrice' => 150,
],
],
'incomplete object' => [
$incompleteObject,
[
'$__id__$' => $incompleteObjectId,
'$__class__$' => '__PHP_Incomplete_Class',
'__PHP_Incomplete_Class_Name' => 'nonExistingClass',
],
],
'integer property object' => [
$integerPropertyObject,
[
'$__id__$' => $integerPropertyObjectId,
'$__class__$' => stdClass::class,
'5' => 5,
],
],
'empty object' => [
$emptyObject,
[
'$__id__$' => $emptyObjectId,
'$__class__$' => stdClass::class,
],
],
'short function' => [
// @formatter:off
fn () => 1,
// @formatter:on
'fn () => 1',
],
'short static function' => [
// @formatter:off
static fn () => 1,
// @formatter:on
'static fn () => 1',
],
'function' => [
function () {
return 1;
},
'function () {
return 1;
}',
],
'static function' => [
static function () {
return 1;
},
'static function () {
return 1;
}',
],
'string' => [
'Hello, Yii!',
'Hello, Yii!',
],
'empty string' => [
'',
'',
],
'null' => [
null,
null,
],
'integer' => [
1,
1,
],
'integer with separator' => [
1_23_456,
123456,
],
'boolean' => [
true,
true,
],
'resource' => [
fopen('php://input', 'rb'),
'{resource}',
],
'empty array' => [
[],
[],
],
'array of 3 elements, automatic keys' => [
[
'one',
'two',
'three',
],
[
'one',
'two',
'three',
],
],
'array of 3 elements, custom keys' => [
[
2 => 'one',
'two' => 'two',
0 => 'three',
],
[
2 => 'one',
'two' => 'two',
0 => 'three',
],
],
'closure in array' => [
// @formatter:off
[fn () => new DateTimeZone('')],
["fn () => new \DateTimeZone('')"],
],
'original class name' => [
// @formatter:off
static fn (VarDumper $date) => new DateTimeZone(''),
// @formatter:on
'static fn (\Yiisoft\\VarDumper\VarDumper $date) => new \DateTimeZone(\'\')',
],
'class alias' => [
// @formatter:off
fn (Dumper $date) => new DateTimeZone(''),
// @formatter:on
'fn (\Yiisoft\VarDumper\VarDumper $date) => new \DateTimeZone(\'\')',
],
'namespace alias' => [
// @formatter:off
fn (VD\VarDumper $date) => new DateTimeZone(''),
// @formatter:on
'fn (\Yiisoft\VarDumper\VarDumper $date) => new \DateTimeZone(\'\')',
],
'closure with null-collision operator' => [
// @formatter:off
fn () => $_ENV['var'] ?? null,
// @formatter:on
'fn () => $_ENV[\'var\'] ?? null',
],
'utf8 supported' => [
'🤣',
'🤣',
],
'closure in property supported' => [
$objectWithClosureInProperty,
[
'$__id__$' => $objectWithClosureInPropertyId,
'$__class__$' => stdClass::class,
'a' => 'fn () => 1',
],
],
'private properties supported' => [
$objectWithPrivateProperties,
[
'$__id__$' => "$objectWithPrivatePropertiesId",
'$__class__$' => "$objectWithPrivatePropertiesClass",
'age' => 0,
'names' => [
'first',
'last',
],
],
],
'nested properties limit' => [
$nestedObject,
[
'$__id__$' => "$nestedObjectId",
'$__class__$' => stdClass::class,
'nested' => [
'$__id__$' => "$nestedObjectId",
'$__class__$' => stdClass::class,
'nested' => [
'$__id__$' => "$nestedObjectId",
'$__class__$' => stdClass::class,
'nested' => [
'$__id__$' => "$nestedObjectId",
'$__class__$' => stdClass::class,
'$__depth_limit_exceeded__$' => true,
],
],
],
],
],
'nested array limit' => [
[
[
[
[
[],
],
],
],
],
[
[
[
[
'$__depth_limit_exceeded__$' => true,
],
],
],
],
],
];
}

public function testDFunction(): void
{
d($variable = 'content');
Expand Down

0 comments on commit d2cae7b

Please sign in to comment.