Skip to content

Commit

Permalink
Optimize Dumper (#231)
Browse files Browse the repository at this point in the history
  • Loading branch information
xepozz authored Jan 4, 2024
1 parent e61844e commit d5232f6
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 41 deletions.
53 changes: 33 additions & 20 deletions src/Dumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ final class Dumper
private array $objects = [];

private static ?ClosureExporter $closureExporter = null;
private array $excludedClasses = [];

/**
* @param mixed $variable Variable to dump.
*/
private function __construct(private mixed $variable, private array $excludedClasses = [])
private function __construct(private mixed $variable, array $excludedClasses = [])
{
$this->excludedClasses = array_flip($excludedClasses);
}

/**
Expand All @@ -42,7 +44,7 @@ public static function create(mixed $variable, array $excludedClasses = []): sel
*/
public function asJson(int $depth = 50, bool $format = false): string|bool
{
return $this->asJsonInternal($this->variable, $format, $depth, 0);
return $this->asJsonInternal($this->variable, $format, $depth, 0, false, true);
}

/**
Expand All @@ -57,7 +59,7 @@ public function asJsonObjectsMap(int $depth = 50, bool $prettyPrint = false): st
{
$this->buildObjectsCache($this->variable, $depth);

return $this->asJsonInternal($this->objects, $prettyPrint, $depth, 1);
return $this->asJsonInternal($this->objects, $prettyPrint, $depth, 1, true, false);
}

private function buildObjectsCache($variable, int $depth, int $level = 0): void
Expand All @@ -66,11 +68,12 @@ private function buildObjectsCache($variable, int $depth, int $level = 0): void
return;
}
if (is_object($variable)) {
if (in_array($variable, $this->objects, true)
|| in_array($variable::class, $this->excludedClasses, true)) {
if (array_key_exists($variable::class, $this->excludedClasses) ||
array_key_exists($objectDescription = $this->getObjectDescription($variable), $this->objects)
) {
return;
}
$this->objects[] = $variable;
$this->objects[$objectDescription] = $variable;
$variable = $this->getObjectProperties($variable);
}
if (is_array($variable)) {
Expand All @@ -80,21 +83,27 @@ private function buildObjectsCache($variable, int $depth, int $level = 0): void
}
}

private function asJsonInternal($variable, bool $format, int $depth, int $objectCollapseLevel): string|bool
{
private function asJsonInternal(
$variable,
bool $format,
int $depth,
int $objectCollapseLevel,
bool $inlineObject,
bool $buildCache,
): string|bool {
$options = JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE;

if ($format) {
$options |= JSON_PRETTY_PRINT;
}
if ($buildCache) {
$this->buildObjectsCache($variable, $depth);
}

return json_encode($this->dumpNested($variable, $depth, $objectCollapseLevel), $options);
}

private function dumpNested($variable, int $depth, int $objectCollapseLevel): mixed
{
$this->buildObjectsCache($variable, $depth);
return $this->dumpNestedInternal($variable, $depth, 0, $objectCollapseLevel);
return json_encode(
$this->dumpNestedInternal($variable, $depth, 0, $objectCollapseLevel, $inlineObject),
$options,
);
}

private function getObjectProperties(object $var): array
Expand All @@ -106,7 +115,7 @@ private function getObjectProperties(object $var): array
return (array)$var;
}

private function dumpNestedInternal($var, int $depth, int $level, int $objectCollapseLevel = 0): mixed
private function dumpNestedInternal($var, int $depth, int $level, int $objectCollapseLevel, bool $inlineObject): mixed
{
$output = $var;

Expand All @@ -119,13 +128,13 @@ private function dumpNestedInternal($var, int $depth, int $level, int $objectCol
$output = [];
foreach ($var as $key => $value) {
$keyDisplay = str_replace("\0", '::', trim((string)$key));
$output[$keyDisplay] = $this->dumpNestedInternal($value, $depth, $level + 1, $objectCollapseLevel);
$output[$keyDisplay] = $this->dumpNestedInternal($value, $depth, $level + 1, $objectCollapseLevel, $inlineObject);
}

break;
case 'object':
$objectDescription = $this->getObjectDescription($var);
if ($depth <= $level || in_array($var::class, $this->excludedClasses, true)) {
if ($depth <= $level || array_key_exists($var::class, $this->excludedClasses)) {
$output = $objectDescription . ' (...)';
break;
}
Expand All @@ -135,7 +144,7 @@ private function dumpNestedInternal($var, int $depth, int $level, int $objectCol
break;
}

if ($objectCollapseLevel < $level && in_array($var, $this->objects, true)) {
if ($objectCollapseLevel < $level && array_key_exists($objectDescription, $this->objects)) {
$output = 'object@' . $objectDescription;
break;
}
Expand All @@ -155,9 +164,13 @@ private function dumpNestedInternal($var, int $depth, int $level, int $objectCol
$value,
$depth,
$level + 1,
$objectCollapseLevel
$objectCollapseLevel,
$inlineObject,
);
}
if ($inlineObject) {
$output = $output[$objectDescription];
}
break;
case 'resource':
case 'resource (closed)':
Expand Down
8 changes: 2 additions & 6 deletions src/Storage/FileStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,8 @@ public function flush(): void
try {
FileHelper::ensureDirectory($basePath);
$dumper = Dumper::create($this->getData(), $this->excludedClasses);
$jsonData = $dumper->asJson();
file_put_contents($basePath . self::TYPE_DATA . '.json', $jsonData);

$jsonObjects = Json::decode($dumper->asJsonObjectsMap());
$jsonObjects = $this->reindexObjects($jsonObjects);
file_put_contents($basePath . self::TYPE_OBJECTS . '.json', Dumper::create($jsonObjects)->asJson());
file_put_contents($basePath . self::TYPE_DATA . '.json', $dumper->asJson(30));
file_put_contents($basePath . self::TYPE_OBJECTS . '.json', $dumper->asJsonObjectsMap(30));

$summaryData = Dumper::create($this->collectSummaryData())->asJson();
file_put_contents($basePath . self::TYPE_SUMMARY . '.json', $summaryData);
Expand Down
8 changes: 2 additions & 6 deletions tests/Unit/DumperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ final class DumperTest extends TestCase
{
/**
* @dataProvider asJsonObjectMapDataProvider
*
* @param string $expectedResult
*
* @group JOM
*/
public function testAsJsonObjectsMap(mixed $var, $expectedResult): void
{
Expand All @@ -40,13 +36,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#{$objectId}":{"public \$id":1}}]
{"stdClass#{$decoratedObjectId}":{"public \$id":1,"public \$name":"Name","public \$originalUser":"object@stdClass#{$objectId}"},"stdClass#{$objectId}":{"public \$id":1}}
S,
],
];
Expand Down
18 changes: 9 additions & 9 deletions tests/Unit/Storage/AbstractStorageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public function testRead(array $data): void
}

$result = $storage->read(StorageInterface::TYPE_DATA);
$encodedResult = \json_decode(Dumper::create($result)->asJson(), true, 512, JSON_THROW_ON_ERROR);
$dumper = Dumper::create($result);
$encodedResult = \json_decode($dumper->asJson(), true, 512, JSON_THROW_ON_ERROR);
$this->assertEquals([$idGenerator->getId() => $encodedExpectedData], $encodedResult);
}

Expand All @@ -69,14 +70,13 @@ abstract public function getStorage(DebuggerIdGenerator $idGenerator): StorageIn

public static function dataProvider(): iterable
{
yield [[1, 2, 3]];
yield [['string']];
yield [[[['', 0, false]]]];
yield [['test']];
yield [[false]];
yield [[null]];
yield [[0]];
yield [[new stdClass()]];
yield 'integers' => [[1, 2, 3]];
yield 'string' => [['string']];
yield 'empty values' => [[[['', 0, false]]]];
yield 'false' => [[false]];
yield 'null' => [[null]];
yield 'zero' => [[0]];
yield 'stdClass' => [[new stdClass()]];
}

protected function createFakeCollector(array $data)
Expand Down

0 comments on commit d5232f6

Please sign in to comment.